I would like to create a Liferay hook that creates public pages on server start.
I already have the hook bound to server start. But I have some problems with creating the page. Maybe I am wrong about user, group, community, etc. (remember that this hook doesn't have access to themeDisplay).
Company company = CompanyLocalServiceUtil.getCompanyByMx(PropsUtil.get(PropsKeys.COMPANY_DEFAULT_WEB_ID));
long companyId = company.getCompanyId();
User defaultUser = UserLocalServiceUtil.getDefaultUser(companyId);
long userId = defaultUser.getUserId();
long groupId = GroupLocalServiceUtil.getCompanyGroup(PortalUtil.getDefaultCompanyId()).getGroupId();
boolean privateLayout = false;
long parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
String name = page.getName();
String title = null;
String description = null;
String type = LayoutConstants.TYPE_PORTLET;
boolean hidden = false;
String friendlyUrl = "/test";
ServiceContext serviceContext = new ServiceContext();
serviceContext.setScopeGroupId(groupId);
LayoutLocalServiceUtil.addLayout(userId, groupId, privateLayout, parentLayoutId, name, title, description, type, hidden, friendlyUrl, serviceContext);
LayoutTypePortlet layoutTypePortlet = (LayoutTypePortlet) layout.getLayoutType();
layoutTypePortlet.setLayoutTemplateId(userId, page.getLayoutId());
LayoutLocalServiceUtil.updateLayout(layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(), layout.getTypeSettings());
The page is never listed...
You might want to check the leftovers of that old sevencogs hook demo code - James Falkner has blogged about it and resurrected some of the code. It might not be for the current version, but if there are any API changes, they're minor.
Pay special attention to the "Adding a Layout (Page) to a Site" paragraph in that article and compare it with your code.
Also note that "on server start" means that you'll have to pay attention to not create the same page twice. It'd happen on every single server start - or actually on every deployment of the hook that you write.
Related
We've migrated from adal4j to msal4j in our java web applications.
All works well but the big difference is that when the user is already logged (maybe in other applications but same browser session) we always see the "select user" page and the user is not logged automatically and redirected to redirect uri as before with adal4j.
This is how we redirect to autentication page:
private static void redirectToAuthorizationEndpoint(IdentityContextAdapter contextAdapter) throws IOException {
final IdentityContextData context = contextAdapter.getContext();
final String state = UUID.randomUUID().toString();
final String nonce = UUID.randomUUID().toString();
context.setStateAndNonce(state, nonce);
contextAdapter.setContext(context);
final ConfidentialClientApplication client = getConfidentialClientInstance();
AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters
.builder(props.getProperty("aad.redirectURI"), Collections.singleton(props.getProperty("aad.scopes"))).responseMode(ResponseMode.QUERY)
.prompt(Prompt.SELECT_ACCOUNT).state(state).nonce(nonce).build();
final String authorizeUrl = client.getAuthorizationRequestUrl(parameters).toString();
contextAdapter.redirectUser(authorizeUrl);
}
I've tried to remove .prompt(Prompt.SELECT_ACCOUNT)
but I receive an error
Any ideas?
• You might be getting the option for selecting the user account after switching to MSAL4J in your browser even after the SSO is enabled because either clearing the token cache is enabled in your code or MsalInteractionRequiredException option is thrown and specified accordingly due to which the application asks for a token interactively.
Thus, please check which accounts information is stored in the cache as below: -
ConfidentialClientApplication pca = new ConfidentialClientApplication.Builder(
labResponse.getAppId()).
authority(TestConstants.ORGANIZATIONS_AUTHORITY).
build();
Set<IAccount> accounts = pca.getAccounts().join(); ’
Then, from the above information, if you want to remove the accounts whose prompts you don’t want to see during the user account selection such that the default account should get selected and signed in automatically, execute the below code by modifying the required information: -
Set<IAccount> accounts = pca.getAccounts().join();
IAccount accountToBeRemoved = accounts.stream().filter(
x -> x.username().equalsIgnoreCase(
UPN_OF_USER_TO_BE_REMOVED)).findFirst().orElse(null);
pca.removeAccount(accountToBeRemoved).join();
• And for the MsalInteractiveRequiredException class in the code, kindly refer to the below official documentation link for the AcquireTokenSilently and other reasons responsible for the behaviour. Also, refer to the sample code given below for your reference regarding the same: -
https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-error-handling-java#msalinteractionrequiredexception
IAuthenticationResult result;
try {
ConfidentialClientApplication application =
ConfidentialClientApplication
.builder("clientId")
.b2cAuthority("authority")
.build();
SilentParameters parameters = SilentParameters
.builder(Collections.singleton("scope"))
.build();
result = application.acquireTokenSilently(parameters).join();
}
catch (Exception ex){
if(ex instanceof MsalInteractionRequiredException){
// AcquireToken by either AuthorizationCodeParameters or DeviceCodeParameters
} else{
// Log and handle exception accordingly
}
}
I need to check through LDAP if an ActiveDirectory user has the PASSWD_CANT_CHANGE flag set. I found the UserAccountControl attribute (https://learn.microsoft.com/it-it/windows/desktop/ADSchema/a-useraccountcontrol): it works for all other flags but it doesn't work for this flag. I only need to read it, not to write.
I'm using Java with UnboundID LDAP SDK (https://ldap.com/unboundid-ldap-sdk-for-java/).
Here is my JUnit test code.
public static enum UACFlags {
SCRIPT(0x0001),
ACCOUNTDISABLE(0x0002),
HOMEDIR_REQUIRED(0x0008),
LOCKOUT(0x0010),
PASSWD_NOTREQD(0x0020),
PASSWD_CANT_CHANGE(0x0040),
ENCRYPTED_TEXT_PWD_ALLOWED(0x0080),
TEMP_DUPLICATE_ACCOUNT(0x0100),
NORMAL_ACCOUNT(0x0200),
INTERDOMAIN_TRUST_ACCOUNT(0x0800),
WORKSTATION_TRUST_ACCOUNT(0x1000),
SERVER_TRUST_ACCOUNT(0x2000),
DONT_EXPIRE_PASSWORD(0x10000),
MNS_LOGON_ACCOUNT(0x20000),
SMARTCARD_REQUIRED(0x40000),
TRUSTED_FOR_DELEGATION(0x80000),
NOT_DELEGATED(0x100000),
USE_DES_KEY_ONLY(0x200000),
DONT_REQ_PREAUTH(0x400000),
PASSWORD_EXPIRED(0x800000),
TRUSTED_TO_AUTH_FOR_DELEGATION(0x1000000);
private int flag;
private UACFlags(int flag) {
this.flag = flag;
}
}
#Test
public void testLDAP() throws LDAPException {
LDAPConnection connection = //GET CONNECTION
String username = "....";
String search = "(sAMAccountName=" + username + ")";
SearchRequest request = new SearchRequest("DC=....,DC=....", SearchScope.SUB, search, SearchRequest.ALL_USER_ATTRIBUTES);
SearchResult result = connection.search(request);
SearchResultEntry entry = result.getSearchEntries().get(0);
Attribute a = entry.getAttribute("userAccountControl");
int val = a.getValueAsInteger();
System.out.println(Integer.toHexString(val));
EnumSet<UACFlags> flags = EnumSet.noneOf(UACFlags.class);
for (UACFlags f : UACFlags.values()) {
if ((val & f.flag) == f.flag) {
flags.add(f);
}
}
System.out.println("FLAGS: " + flags);
}
I set up the flag on AD Users and Computers and it works as expected. I only want to check the flag programmatically, using Java and LDAP. Other solutions than UserAccountControl attribute are ok!
Thanks!!
That is, unfortunately, expected.
Microsoft uses the ADS_USER_FLAG_ENUM enumeration in a couple places:
The userAccountControl attribute when using LDAP, and
The userFlags property when using the WinNT provider.
The ADS_UF_PASSWD_CANT_CHANGE flag can only be used when using the WinNT provider, which I'm not sure you can do from Java.
When you click that 'User cannot change password' checkbox in AD Users and Computers, it doesn't actually change the userAccountControl attribute. In reality, it adds two permissions on the account:
Deny Change Password to 'Everyone'
Deny Change Password to 'SELF'
There is a description of how to look for those permissions here, but the examples are in C++ and VBScript. I don't know how to view the permissions in Java. It seems difficult and I can't find any real examples.
UPDATE
Appears from AD 2008 on that this is not a "real" value; but rather an ACE within the ACL of the entry.
THIS NO LONGER WORKS
As far as I can tell.
Microsoft Active Directory has a neat Extensible matching value that should work called LDAP_MATCHING_RULE_BIT_AND
So a simple LDAP Query Filter like:
(userAccountControl:1.2.840.113556.1.4.803:=64)
Should do the trick.
I am attempting to create new Interactions programmatically on Genesys Platform SDK 8.5 for Java.
I use the example on the API reference
public void createInteraction(String ixnType, String ixnSubtype, String queue) throws Exception
{
RequestSubmit req = RequestSubmit.create();
req.setInteractionType(ixnType);
req.setInteractionSubtype(ixnSubtype);
req.setQueue(queue);
req.setMediaType("email");
Message response = mPMService.getProtocol("IxnSrv").request(req);
if(response == null || response.messageId() != EventAck.ID) {
// For this sample, no error handling is implemented
return;
}
EventAck event = (EventAck)response;
mInteractionId = event.getExtension().getString("InteractionId");
}
However, this gives me an Unsupported protocol element error.
'EventError' (126) attributes:
attr_error_desc [str] = "Unsupported protocol element"
attr_ref_id [int] = 2
attr_error_code [int] = 4
How do I create a new Interaction programmatically?
Interaction server should be connected with ClientType as either MediaServer or AgentApplication for this request(RequestSubmit).
First of all, you must open your protocol as Media Server. After that you must submit your interaction to interaction server.
Firstly your protocol config must be like this;
interactionServerConfiguration.ClientName = "TestClient";
interactionServerConfiguration.ClientType = InteractionClient.MediaServer;
// Register this connection configuration with Protocol Manager
protocolManagementService.Register(interactionServerConfiguration);
Note : You must have MediaServer type application definition on your Configuration Env., you must see it in CME.
After open you connection to ixn server. You can submit your interaction what you like. Even you can create new type interaction just like i do. I did for our coopate sms system. Its name is not important. We defined it on our bussiness attribute, so our agent can send coopate 3rd party sms system from their agent desktop. Without new extension or new license :) Just tricked it system. Also genesys allows it. i know it because we are genesys official support team in our country :) (But agent seat license may be required depends on agent head count).
RequestSubmit request = RequestSubmit.Create();
request.TenantId = 1;
request.MediaType = "email";
request.Queue = c_inboundQueue;
request.InteractionType = "Inbound";
request.InteractionSubtype = "InboundNew";
// Prepare the message to send. It is inserted in the request as UserData
KeyValueCollection userData =
new KeyValueCollection();
// Prepare the message to send
userData.Add("Subject", "subject goes here");
request.UserData = userData; protocolManagementService[c_interactionServerConfigurationIdentifier].Send(request);
Turns out I needed to set ClientType to InteractionClient.ReportingEngine.
I am making an android application using IMDB open-source api (My movie api).
Features are:
when user search a particular movie they got the list in list view. If they click on a list it shows full details of the movie.
User also can add any movie to favourite list and also can delete it.
Everything works fine. BUT THE APPLICATION FORCE CLOSES IF ANY FIELD IS MISSING FOR A MOVIE ON IMDB DATABASE LIKE MOVIE LANGUAGE OR DURATION ETC.
I have tried if- else syntax but not worked. If have any suggestion please let me know. I will be thankful to you.
Here is my code:
ImageProvider Ip = new ImageProvider();
final String Title = getIntent().getStringExtra("title");
final String story = getIntent().getStringExtra("story");
final String actors = getIntent().getStringExtra("actors");
final String lang = getIntent().getStringExtra("lang");
final String Id = getIntent().getStringExtra("ID");
final String duration = getIntent().getStringExtra("time");
final String directBy = getIntent().getStringExtra("director");
final String year1 = getIntent().getStringExtra("year");
final String src = getIntent().getStringExtra("img");
Log.v("src", src);
title.setText(Title);
details.setText(story);
cast.setText(actors);
language.setText(lang);
mid.setText(Id);
time.setText(duration);
Director.setText(directBy);
year.setText(year1);
VImg.setImageBitmap(Ip.fetchImage(src));
How to obtain page's organization in liferay portlet correctly?
I tried:
Company. Is not an organization, but a portal instance.
Group. Is group of current user, not of current page.
UPDATE
I am in the portlet class' doView method. I know how to pass anything I can obtain here upwards to JSP to be accessible via EL/JSTL.
UPDATE 2
group.getOrganizationId() always returns zero.
UPDATE 3
This code I use to prepare variables
private void storeVariables(RenderRequest renderRequest) {
PortletPreferences prefs = renderRequest.getPreferences();
String image_id = (String) prefs.getValue("image_id", "communicator");
ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(WebKeys.THEME_DISPLAY);
Company company = themeDisplay.getCompany();
Group group = themeDisplay.getScopeGroup();
log.info("group = {}", group);
long organizationId = group.getOrganizationId();
log.info("organizationId = {}", organizationId);
PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
String contextPath = renderRequest.getContextPath();
if( !contextPath.endsWith("/") ) {
contextPath = contextPath + "/";
}
renderRequest.setAttribute("images", images);
renderRequest.setAttribute("image", images.get(image_id));
renderRequest.setAttribute("image_id", image_id);
renderRequest.setAttribute("themeDisplay", themeDisplay);
renderRequest.setAttribute("portletDisplay", portletDisplay);
renderRequest.setAttribute("contextPath", contextPath);
}
UPDATE 3
The following code in JSP returns empty string
<!-- scopeGroupId = <c:out value="${scopeGroupId}"/> -->
A group is a container of content and pages, and it's the internal entity for sites, layout scopes, staging and so on.
In Liferay 6.1, a site (which was called community in previous versions) can be associated to an organization. It depends on where you are (in a JSP, in the portlet class, etc.), but, if you have the entity representing the current Group, you can write something like this:
Organization organization = null;
if (group.isOrganization()) {
organization = OrganizationLocalServiceUtil.getOrganization(group.getOrganizationId());
}
Hope it helps. Ask if you need help in order to retrieve the Group object...