Customizing LifeRay portlet using jspf hook - liferay

i need to customize the create account portlet, i want to hide the filed "middle name" , but that field exists under the file /html/portlet/login/create_account_user_name.jspf, using the hook for customizing jsp pages didn't work because that file is a "jspf" not a "jsp" and it's not displayed in the eclipse window of jsp files available for hook change
Have someone a solution for that situation?
Content of create_account_user_name.jspf :
<aui:input autoFocus="<%= windowState.equals(WindowState.MAXIMIZED) %>" model="<%= User.class %>" name="firstName" />
<aui:input model="<%= User.class %>" name="middleName" />
<aui:input model="<%= User.class %>" name="lastName">
<c:if test="<%= PrefsPropsUtil.getBoolean(company.getCompanyId(), PropsKeys.USERS_LAST_NAME_REQUIRED, PropsValues.USERS_LAST_NAME_REQUIRED) %>">
<aui:validator name="required" />
</c:if>
</aui:input>
Content of create_account.jsp :
<%# include file="/html/portlet/login/init.jsp" %>
<%
String redirect = ParamUtil.getString(request, "redirect");
String openId = ParamUtil.getString(request, "openId");
boolean male = ParamUtil.getBoolean(request, "male", true);
Calendar birthdayCalendar = CalendarFactoryUtil.getCalendar();
birthdayCalendar.set(Calendar.MONTH, Calendar.JANUARY);
birthdayCalendar.set(Calendar.DATE, 1);
birthdayCalendar.set(Calendar.YEAR, 1970);
%>
<portlet:actionURL secure="<%= PropsValues.COMPANY_SECURITY_AUTH_REQUIRES_HTTPS || request.isSecure() %>" var="createAccountURL">
<portlet:param name="struts_action" value="/login/create_account" />
</portlet:actionURL>
<aui:form action="<%= createAccountURL %>" method="post" name="fm">
<aui:input name="saveLastPath" type="hidden" value="<%= false %>" />
<aui:input name="<%= Constants.CMD %>" type="hidden" value="<%= Constants.ADD %>" />
<aui:input name="redirect" type="hidden" value="<%= redirect %>" />
<aui:input name="openId" type="hidden" value="<%= openId %>" />
<liferay-ui:error exception="<%= AddressCityException.class %>" message="please-enter-a-valid-city" />
<liferay-ui:error exception="<%= AddressStreetException.class %>" message="please-enter-a-valid-street" />
<liferay-ui:error exception="<%= AddressZipException.class %>" message="please-enter-a-valid-postal-code" />
<liferay-ui:error exception="<%= CaptchaMaxChallengesException.class %>" message="maximum-number-of-captcha-attempts-exceeded" />
<liferay-ui:error exception="<%= CaptchaTextException.class %>" message="text-verification-failed" />
<liferay-ui:error exception="<%= CompanyMaxUsersException.class %>" message="unable-to-create-user-account-because-the-maximum-number-of-users-has-been-reached" />
<liferay-ui:error exception="<%= ContactFirstNameException.class %>" message="please-enter-a-valid-first-name" />
<liferay-ui:error exception="<%= ContactFullNameException.class %>" message="please-enter-a-valid-first-middle-and-last-name" />
<liferay-ui:error exception="<%= ContactLastNameException.class %>" message="please-enter-a-valid-last-name" />
<liferay-ui:error exception="<%= DuplicateOpenIdException.class %>" message="a-user-with-that-open-id-already-exists" />
<liferay-ui:error exception="<%= DuplicateUserEmailAddressException.class %>" message="the-email-address-you-requested-is-already-taken" />
<liferay-ui:error exception="<%= DuplicateUserIdException.class %>" message="the-user-id-you-requested-is-already-taken" />
<liferay-ui:error exception="<%= DuplicateUserScreenNameException.class %>" message="the-screen-name-you-requested-is-already-taken" />
<liferay-ui:error exception="<%= EmailAddressException.class %>" message="please-enter-a-valid-email-address" />
<liferay-ui:error exception="<%= GroupFriendlyURLException.class %>">
<%
GroupFriendlyURLException gfurle = (GroupFriendlyURLException)errorException;
%>
<c:if test="<%= gfurle.getType() == GroupFriendlyURLException.DUPLICATE %>">
<liferay-ui:message key="the-screen-name-you-requested-is-associated-with-an-existing-friendly-url" />
</c:if>
</liferay-ui:error>
<liferay-ui:error exception="<%= NoSuchCountryException.class %>" message="please-select-a-country" />
<liferay-ui:error exception="<%= NoSuchListTypeException.class %>" message="please-select-a-type" />
<liferay-ui:error exception="<%= NoSuchRegionException.class %>" message="please-select-a-region" />
<liferay-ui:error exception="<%= PhoneNumberException.class %>" message="please-enter-a-valid-phone-number" />
<liferay-ui:error exception="<%= RequiredFieldException.class %>" message="please-fill-out-all-required-fields" />
<liferay-ui:error exception="<%= ReservedUserEmailAddressException.class %>" message="the-email-address-you-requested-is-reserved" />
<liferay-ui:error exception="<%= ReservedUserIdException.class %>" message="the-user-id-you-requested-is-reserved" />
<liferay-ui:error exception="<%= ReservedUserScreenNameException.class %>" message="the-screen-name-you-requested-is-reserved" />
<liferay-ui:error exception="<%= TermsOfUseException.class %>" message="you-must-agree-to-the-terms-of-use" />
<liferay-ui:error exception="<%= UserEmailAddressException.class %>" message="please-enter-a-valid-email-address" />
<liferay-ui:error exception="<%= UserIdException.class %>" message="please-enter-a-valid-user-id" />
<liferay-ui:error exception="<%= UserPasswordException.class %>">
<%
UserPasswordException upe = (UserPasswordException)errorException;
%>
<c:if test="<%= upe.getType() == UserPasswordException.PASSWORD_CONTAINS_TRIVIAL_WORDS %>">
<liferay-ui:message key="that-password-uses-common-words-please-enter-in-a-password-that-is-harder-to-guess-i-e-contains-a-mix-of-numbers-and-letters" />
</c:if>
<c:if test="<%= upe.getType() == UserPasswordException.PASSWORD_INVALID %>">
<liferay-ui:message key="that-password-is-invalid-please-enter-in-a-different-password" />
</c:if>
<c:if test="<%= upe.getType() == UserPasswordException.PASSWORD_LENGTH %>">
<%
PasswordPolicy passwordPolicy = PasswordPolicyLocalServiceUtil.getDefaultPasswordPolicy(company.getCompanyId());
%>
<%= LanguageUtil.format(pageContext, "that-password-is-too-short-or-too-long-please-make-sure-your-password-is-between-x-and-512-characters", String.valueOf(passwordPolicy.getMinLength()), false) %>
</c:if>
<c:if test="<%= upe.getType() == UserPasswordException.PASSWORD_TOO_TRIVIAL %>">
<liferay-ui:message key="that-password-is-too-trivial" />
</c:if>
<c:if test="<%= upe.getType() == UserPasswordException.PASSWORDS_DO_NOT_MATCH %>">
<liferay-ui:message key="the-passwords-you-entered-do-not-match-each-other-please-re-enter-your-password" />
</c:if>
</liferay-ui:error>
<liferay-ui:error exception="<%= UserScreenNameException.class %>" message="please-enter-a-valid-screen-name" />
<liferay-ui:error exception="<%= WebsiteURLException.class %>" message="please-enter-a-valid-url" />
<c:if test='<%= SessionMessages.contains(request, "openIdUserInformationMissing") %>'>
<div class="alert alert-info">
<liferay-ui:message key="you-have-successfully-authenticated-please-provide-the-following-required-information-to-access-the-portal" />
</div>
</c:if>
<aui:model-context model="<%= Contact.class %>" />
<aui:fieldset column="<%= true %>">
<aui:col width="<%= 50 %>">
<%# include file="/html/portlet/login/create_account_user_name.jspf" %>
<c:if test="<%= !PrefsPropsUtil.getBoolean(company.getCompanyId(), PropsKeys.USERS_SCREEN_NAME_ALWAYS_AUTOGENERATE) %>">
<aui:input model="<%= User.class %>" name="screenName" />
</c:if>
<aui:input autoFocus="<%= true %>" model="<%= User.class %>" name="emailAddress">
<c:if test="<%= PrefsPropsUtil.getBoolean(company.getCompanyId(), PropsKeys.USERS_EMAIL_ADDRESS_REQUIRED) %>">
<aui:validator name="required" />
</c:if>
</aui:input>
</aui:col>
<aui:col width="<%= 50 %>">
<c:if test="<%= PropsValues.LOGIN_CREATE_ACCOUNT_ALLOW_CUSTOM_PASSWORD %>">
<aui:input label="password" name="password1" size="30" type="password" value="" />
<aui:input label="enter-again" name="password2" size="30" type="password" value="">
<aui:validator name="equalTo">
'#<portlet:namespace />password1'
</aui:validator>
</aui:input>
</c:if>
<c:choose>
<c:when test="<%= PrefsPropsUtil.getBoolean(company.getCompanyId(), PropsKeys.FIELD_ENABLE_COM_LIFERAY_PORTAL_MODEL_CONTACT_BIRTHDAY) %>">
<aui:input name="birthday" value="<%= birthdayCalendar %>" />
</c:when>
<c:otherwise>
<aui:input name="birthdayMonth" type="hidden" value="<%= Calendar.JANUARY %>" />
<aui:input name="birthdayDay" type="hidden" value="1" />
<aui:input name="birthdayYear" type="hidden" value="1970" />
</c:otherwise>
</c:choose>
<c:if test="<%= PrefsPropsUtil.getBoolean(company.getCompanyId(), PropsKeys.FIELD_ENABLE_COM_LIFERAY_PORTAL_MODEL_CONTACT_MALE) %>">
<aui:select label="gender" name="male">
<aui:option label="male" value="1" />
<aui:option label="female" selected="<%= !male %>" value="0" />
</aui:select>
</c:if>
<c:if test="<%= PropsValues.CAPTCHA_CHECK_PORTAL_CREATE_ACCOUNT %>">
<portlet:resourceURL var="captchaURL">
<portlet:param name="struts_action" value="/login/captcha" />
</portlet:resourceURL>
<liferay-ui:captcha url="<%= captchaURL %>" />
</c:if>
</aui:col>
</aui:fieldset>
<aui:button-row>
<aui:button type="submit" />
</aui:button-row>
</aui:form>
<liferay-util:include page="/html/portlet/login/navigation.jsp" />

just copy the original file /html/portlet/login/create_account_user_name.jspf inside your docroot/custom_jsp/html/portlet/login/ directory. Despite what eclipse shows to you, any jsp/jspf of your hook will replace the original liferay file.
I successfully edited file /html/portlet/users_admin/user/details_user_name.jspf (i disabled field modifications for users coming from ldap).
Please note that in liferay-hook.xml the only directive you can set for jsp overriding is
<custom-jsp-dir>/custom_jsp</custom-jsp-dir>
You wont need to specify all jsp files, just your root directory

Related

Handling authentication failure in auto login in liferay

I have a theme where I have a popup to ask for the login credentials .
It has 2 fields ,login id and password followed by a submit button.
<div class="x">
<div class="y">
<aui:input name="login" id="login" class="z"
type="text" placeholder="Email" showRequiredLabel="<%=false%>" label="" value="<%=login%>">
</aui:input>
</div>
</div>
<div class="x">
<div class="y">
<aui:input name="password" id="Password"
class="z" type="password" placeholder="Password"
showRequiredLabel="<%=false%>" label="" value="<%=password%>">
</aui:input>
</div>
</div>
<div class="x">
<div class="y">
<aui:button-row>
<aui:button type="submit" class="btn z"
value="Log in" id=z/>
</aui:button-row>
</div>
</div>
<script>
jQuery(document).ready(function($) {
$('#z').click(function(){
var textBoxEmail= $('#login').val();
var textBoxPassword= $('#Password').val();
var redirecturl="/home";
var url = Liferay.ThemeDisplay.getPortalURL()+"/c/portal/login?login=" + textBoxEmail + "&password=" +textBoxPassword+"&rememberMe=false&redirect=" + redirecturl;
$("#loginDetails").attr('action',url);
document.getElementById('loginDetails').submit();
}
});
</script>
This logins for the positive case , but if the password or the email entered is incorrecet it displays the
"This webpage is not available
ERR_CONTENT_DECODING_FAILED"
I want to show the failure message in the same page from where i am sending the login details or I want it to be redirected to some URL if the authentication fails.
I am using liferay-6.2-ce-ga3 and the theme is designed in the velocity.
You could redirect to /c/portal/login?redirect=currenturl which redirects to the current url. Writing a Hook is another option if you want to customize more.
So before you even start I would question your design from an architectural standpoint. In Liferay, the login functionality is actually its own portlet (called the login portlet). The correct way to modify the login functionality is via a hook. However, to answer your question more directly, I would modify your code as such (most of this is taken from Liferay's login.jsp).
<portlet:actionURL secure="<%= PropsValues.COMPANY_SECURITY_AUTH_REQUIRES_HTTPS || request.isSecure() %>" var="loginURL">
<portlet:param name="struts_action" value="/login/login" />
</portlet:actionURL>
<aui:form action="<%= loginURL %>" autocomplete='<%= PropsValues.COMPANY_SECURITY_LOGIN_FORM_AUTOCOMPLETE ? "on" : "off" %>' cssClass="sign-in-form" method="post" name="fm">
<aui:input name="saveLastPath" type="hidden" value="<%= false %>" />
<aui:input name="redirect" type="hidden" value="<%= redirect %>" />
<aui:input name="doActionAfterLogin" type="hidden" value="<%= portletName.equals(PortletKeys.FAST_LOGIN) ? true : false %>" />
<%
String loginLabel = null;
String authType = portletPreferences.getValue("authType", StringPool.BLANK);
if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
loginLabel = "email-address";
} else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
loginLabel = "screen-name";
} else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
loginLabel = "id";
}
%>
<aui:input autoFocus="<%= windowState.equals(LiferayWindowState.EXCLUSIVE) || windowState.equals(WindowState.MAXIMIZED) %>" cssClass="clearable" label="<%= loginLabel %>" name="login" showRequiredLabel="<%= false %>" type="text" value="<%= login %>">
<aui:validator name="required" />
</aui:input>
<aui:input name="password" showRequiredLabel="<%= false %>" type="password" value="<%= password %>">
<aui:validator name="required" />
</aui:input>
<span id="<portlet:namespace />passwordCapsLockSpan" style="display: none;"><liferay-ui:message key="caps-lock-is-on" /></span>
<aui:button-row>
<aui:button type="submit" value="sign-in" />
</aui:button-row>
</aui:form>
<aui:script use="aui-base">
var password = A.one('#<portlet:namespace />password');
if (password) {
password.on('keypress', function(event) {
Liferay.Util.showCapsLock(event, '<portlet:namespace />passwordCapsLockSpan');
});
}
</aui:script>
I agree, go with the Login hook or with authentication pipeline using pre and post login filters. The redirection can be done from filters.

Liferay SearchContainer with multiple classes

I want to make a date list with patients and doctors, in database have 1: N, and the patients is reference by the id, when i do a simple serach-container the column doctorName is null because the patient class has not a name namedDoctor , Only have idDoctor and the doctorName it owns a doctor class, so i have two classes and 1 search-container and i do not know how to put the names of doctors :/
Search-container
' emptyResultsMessage="empty-cita-menssage-result">
"
total="<%= CitaLocalServiceUtil.getCitasCount() %>"
/>
<
<liferay-ui:search-container-row className="com.everis.formacion.model.Cita"
keyProperty="idCita"
modelVar="cita"
escapedModel="<%= true %>">
<liferay-ui:search-container-column-text
name="fechaCita"
property="<%= CitaPortlet.REQUEST_FECHA_PACIENTE_PARAM %>"
/>
<liferay-ui:search-container-column-text
name="nombrePaciente"
property="<%= CitaPortlet.REQUEST_NOMBRE_PACIENTE_PARAM %>"
/>
<liferay-ui:search-container-column-text
name="nombreDoctor"
property="<%= DoctorPortlet.REQUEST_NOMBRE_PARAM %>"
/>
<liferay-ui:search-container-column-text
name="comentarios"
property="<%= CitaPortlet.REQUEST_COMENTARIO_PARAM %>"
/>
</liferay-ui:search-container-row>
<liferay-ui:search-iterator />
<liferay-ui:search-container-column-text
value="<%= DoctorLocalServiceUtil.getDoctor(cita.getIdDoctor()).getNombreDoctor() %>"
name="Nombre Doctor"
/>
with this return the name of the doctor :)

Invoke action of core Liferay's portlet (Document Library) using custom portlet's form

I need to call document library portlet's EditFileEntryAction (core liferay) on submitting my custom form.
I have created following actionURL:
<liferay-portlet:actionURL var="editFileEntryURL" portletName="<%=PortletKeys.DOCUMENT_LIBRARY %>" doAsGroupId="${scopeGroupId}" refererPlid="${plid}">
<portlet:param name="struts_action" value="/document_library/edit_file_entry" />
<portlet:param name="uploader" value="classic" />
</liferay-portlet:actionURL>
and I want to submit below form:
<aui:form action="<%= editFileEntryURL %>" cssClass="lfr-dynamic-form" enctype="multipart/form-data" method="post" name="fm">
<aui:input name="<%= Constants.CMD %>" type="hidden" />
<aui:input name="uploadProgressId" type="hidden" value="<%= uploadProgressId %>" />
<aui:input name="repositoryId" type="hidden" value="${themeDisplay.scopeGroupId}" />
<aui:input name="folderId" type="hidden" value="${categoryFolderId}" />
<aui:input name="fileEntryId" type="hidden" value="0" />
<aui:input name="workflowAction" type="hidden" value="<%= WorkflowConstants.ACTION_PUBLISH %>" />
<aui:input name="file" style="width: auto;" type="file">
<aui:validator name="acceptFiles">
'<%= StringUtil.merge(PrefsPropsUtil.getStringArray(PropsKeys.DL_FILE_EXTENSIONS, StringPool.COMMA)) %>'
</aui:validator>
</aui:input>
<aui:input name="title">
<aui:validator errorMessage="you-must-specify-a-file-or-a-title" name="custom">
function(val, fieldNode, ruleValue) {`enter code here`
return ((val != '') || A.one('#<portlet:namespace />file').val() != '');
}
</aui:validator>
</aui:input>
<aui:button type="submit" value="save" name="save" />
</aui:form>
I'd recommend to not have the HTTP-level cross-dependency on Liferay's document library portlet. Rather implement your own upload portlet and use the document library API to store the file yourself.

How to add SELECT ALL function in Search Container?

I want to have a SELECT ALL function in my Search Container like this:
This is my code of Search container :
<liferay-ui:search-container delta="5">
<%-- <c:choose>
<c:when test="">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose> --%>
<liferay-ui:search-container-results
results="<%= RegUserAccountLocalServiceUtil.getRegUserAccounts(searchContainer.getStart(), searchContainer.getEnd()) %>"
total="<%= RegUserAccountLocalServiceUtil.getRegUserAccountsCount() %>"
/>
<liferay-ui:search-container-row
className="com.pmti.bir.triu.model.RegUserAccount"
keyProperty="acctId"
modelVar="aRegUserAccount" >
<liferay-ui:search-container-column-text>
<input name="rowChecker" type="checkbox" value="<%=aRegUserAccount.getAcctId()%>" />
</liferay-ui:search-container-column-text>
<liferay-ui:search-container-column-text
property="acctStatusFlag" name="STATUS"
orderable="<%=true %>"/>
<liferay-ui:search-container-column-text property="acctFirstName"
name="FULL NAME" orderable="<%= true %>"/>
<liferay-ui:search-container-column-text property="acctEmailAdd"
name="USERNAME" orderable="<%= true %>"/>
<liferay-ui:search-container-column-text property="acctBusinessName" name="POSITION" orderable="<%= true %>"
orderableProperty="acctLevelStatus"/>
<liferay-ui:search-container-column-text property="createdBy"
name="DIVISION" orderable="<%=true %>"/>
<liferay-ui:search-container-column-text property="acctUsername" name="USER TYPE" orderable="<%= true %>"
orderableProperty="acctUsername"/>
<liferay-ui:search-container-column-jsp
align="right"
path="/html/viewuseraccount/view_user_actions.jsp"
/>
</liferay-ui:search-container-row>
<liferay-ui:search-iterator />
</liferay-ui:search-container>
And this is what it looks like:
How will I achieve to have a Select all inside my Search container? I don't know how. Please help me. Thank you very much in advance! Good day!
You have to specify rowChecker attribute to search-container tag.
e.g. rowChecker=<%=new RowChecker(renderResponse)%>
And you can get all-selected values by example code below.
Liferay.Util.listCheckedExcept(document.<portlet:namespace />fm, "<portlet:namespace />allRowIds");

How to convert a portal URL to its corresponding friendly URL

I have implemented friendly-url successfully for few of my custom portlets and it is working fine.
When click-able links are generated, it correctly shows the friendly-url.
Now my requirement is that, I need to send this render-URL (say URL01) as a parameter (param02) to another URL (URL02) and this URL01 then would be displayed on another page.
This is how URL01 is generated:
<portlet:renderURL var="URL01" windowState="<%=WindowState.MAXIMIZED.toString() %>">
<portlet:param name="redirect" value="<%= currentURL %>" />
<portlet:param name="myId" value="<%= String.valueOf(myObject.getMyId()) %>" />
<portlet:param name="title" value="<%= myObject.getTitle() %>" />
<portlet:param name="name" value="<%= myObject.getName() %>" />
</portlet:renderURL>
This is how URL02 is generated
<portlet:renderURL var="URL02" windowState="<%= LiferayWindowState.POP_UP.toString() %>">
<portlet:param name="redirect" value="<%= currentURL %>" />
<portlet:param name="URL01" value="<%=URL01 %>" />
<portlet:param name="ownerId" value="<%= String.valueOf(ownerId) %>" />
<portlet:param name="groupId" value="<%= String.valueOf(scopeGroupId) %>" />
</portlet:renderURL>
This URL02 would open a pop-up and the URL01 would be displayed as below in the JSP:
URL: <%= ParamUtil.getString(request, "URL01") %>
But this shows URL01 (unfriendly-URL) as:
URL: http://localhost:8080/web/guest/mypage?p_p_id=my_WAR_myportlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_my_WAR_myportlet_myId=10989&_my_WAR_myportlet_title=This+is+miine&my_WAR_myportlet_name=What+name
If this is a clickable link it generates perfectly as (friendly-URL):
Click me!
So I need a utility which can convert my unfriendly-url to friendly-URL, something like if a String of unfriendly-url is passed - it would convert that to the friendly-url shown above.
Or I have to create an implementation of my own to achieve this?
Edit:
<route>
<pattern>/{myId:\d+}/{title:.+}/{name:.+}/{p_p_state}</pattern>
<ignored-parameter name="redirect" />
<implicit-parameter name="p_p_id">my_WAR_myportlet</implicit-parameter>
<implicit-parameter name="p_p_lifecycle">0</implicit-parameter>
<implicit-parameter name="p_p_mode">view</implicit-parameter>
</route>
And yes the URL01 is written above the URL02 in the JSP.
I think you can create your own <portlet-url-class> and it will be used when you create the portlet URL with the <portlet:renderURL> tag.
In liferay-portlet.xml, you can define the <portlet-url-class> entry.
If you check the source code of PortletResponseImpl.java, the method createLiferayPortletURL() checks for the PortletURLGenerationListener for that portlet.
I think, you can create a this one and modify URL as you want to.

Resources