Can the ResourceLocalService be called remotely via the JSON-WS API? - liferay

I'm trying to create a Liferay permissions resource using the JSON-WS API. I haven't found any JSON-WS API registered service methods in http://localhost:8080/api/jsonws for creating Resources.
According to the JSON Web Services docs, you can remotely enable services by adding the #JSONWebService annotation. It is not clear to me how and if you can register Liferay's built-in services if they aren't already exposed.
Also, the Javadocs for ResourceLocalService specifically state:
This is a local service. Methods of this service will not have
security checks based on the propagated JAAS credentials because this
service can only be accessed from within the same VM.
So is it even possible to access methods of ResourceLocalService remotely with the JSON-WS API? If so, can you point me in the right direction of how to do it?
PS: I am successfully using the JSON-WS API in my external application for service methods that are already published and listed in http://localhost:8080/api/jsonws

The approach I've used for this is to write my own service that has no data tables, but exposes some JSON WS methods. You do this in a plugin project using service builder's option for creating remote services (I used a portlet plugin because my app has portlets in it, but I believe it could be done in a hook plugin just as well).
Quick excerpt from a service.xml:
<entity name="UserNotification" local-service="true"
remote-service="true">
</entity>
No fields, no finders... just the entity name.
Then in your plugin project's UserNotificationServiceImpl you create the methods you want to expose and make regular service calls to the Liferay service in question (you are responsible for making use of the permission checker, there's nothing automatic about security here). When you re-build your services ServiceBuilder reverse engineer's your methods and creates the remote service API.
The tricky bit is to then call your custom API, which will have a different form than the calls you make to the built-in API. Assuming you want the service to require authentication and give your method a user context to use with the permission checker you make the call in this form:
https://user:passwd#example.com/api/secure/jsonws/plugin-name.entity-name/method? ...parameters
There are other calling formats, but the key thing is that you address Liferay directly, and then identify the plugin and entity using that dotted notation. If you address your plugin in its own application context
https://user:passwd#example.com/plugin-name/api/secure/jsonws/entity-name/method? ...parameters
You will not get the authentication context, so you won't be able to use the permission checker. Unfortunately you will find a fair amount of material laying around the Liferay site that tells you to make the call this way. Don't.
I haven't addressed all details (configuration settings, calling nuances, etc) But the new documentation in the Developer Guide addresses them fairly well now. So be sure to study that.
You will also want to read up on Service Builder.
But be warned -- you are probably used to using the API page provided by your portal as a reference for the services. This fine for in-built services, but for services provided by plugins, this page is not reliable, as it gives incorrect examples. Go by the docs.

In Liferay - as you point out from the documentation excerpt - *LocalService is only available from the same VM. Services that are available from remote are just *Service (without the Local part) and their implementations are supposed to check permissions, then forward the call to the *LocalService if applicable.
It wouldn't make sense to just add a Resource to Liferay without an actual object, so the ResourceLocalService is supposed to be called by the service that adds another entity (the Resource needs an additional object reference for the actual object, consisting of class name and primary key)

Related

How to incorporate IgnoreAPI into Azure API Management?

So in my API, I have a few secret endpoints hidden from the documentation. This is achieved nicely using the attribute IgnoreAPI. The endpoints aren't dangerous, but I just don't want them advertised to end users.
However, I'm now starting to use Azure API Management, in which you easily configure APIs using Swagger. IgnoreAPI stops the endpoint from going in the Swagger document, and thus, stops the auto-set up from discovering IgnoreAPI attributed endpoints.
Is there a standard way of making certain endpoints invisible on Azure API Management WITHOUT using ignoreAPI? Or is there a way to force in IgnoreAPI endpoints and hide them in the Developer Portal?
One option would be to create the "hidden" operations in a separate API that is attached to a hidden product. Currently there isn't a way to identify specific operations as hidden.
I'm still open to suggestions, but this is the best solution I found:
If you go into the Developer Portal Template Editor, you can edit the markup for the template that shows the list of endpoints. I made a blacklist that will skip my hidden endpoints. It works across all APIs too!

Call external service from SharePoint Online web part

We are in the process of moving an on-premise SharePoint installation to SharePoint Online. We have a number of existing C# web parts that we need to convert. These web parts currently access some of our on-premise data... we need to get the web parts working on SharePoint Online; however, we're not certain of the best approach.
We've looked at BCS, but it seems that it is geared more towards synchronizing lists of data via basic CRUD methods. For many of our applications, we are not looking to synchronize lists, we are looking more towards action-oriented methods on a service that can be called on-demand as needed by the web part.
We don't believe the call can be client-side, as the users will often be accessing SharePoint Online from workstations that are not joined to our domain, and we don't want the user to have to separately authenticate to our service (i.e. we want our service to trust only the SharePoint Online backend).
Our ideal setup would be to have our C# code for the web part call into our web service (hosted on our domain, authenticating with a service account from the SPO secure store), passing the current username from the SharePoint context, and getting back a response that the web part can then use for its processing.
But as we understand, the web parts in SharePoint Online are sandboxed in such a way that they cannot make external HTTPS calls via HttpWebRequest.
We've searched for how-to examples or documentation related to our use case, and haven't found anything saying it's possible or that it's not possible. Does anybody know if it's possible for a web part to get data in this way? Is there some other direction we should be taking to achieve this?
In SharePoint online, if you are developing a SharePoint hosted app; You will be able to call external endpoints (EPs) after adding these endpoints in the manifest file.
If you haven't added these endpoint to the manifest file, This means you are not permitting the app to call an external EPs.
You don't need BCS in SharePoint online to call external EPs. Here is a sample on how to do this using JavaScript.
https://msdn.microsoft.com/en-us/library/office/fp179895.aspx
Let me know if you have any other questions.

Using Azure MobileServices library with my own LAN WebApi

I am currently doing some research for the development of a mobile application for our company that should support offline data sync (on an iPad). We have explored many possibilities including PhoneGap/Cordova, Xamarin and simply native iOS development. Xamarin, for many different reasons, seems to be our best choice, so my question will assume we will develop in Xamarin.
I was looking into a library for managing offline data synchronization and the most obvious solution is Microsoft Azure MobileServices. However, my company is Canadian, and apparently it's hard to trust (legally) our data to clouds based in the US. Since we already deployed internally our WebApi on our intranet, I figured there was probably a way to point the MobileServices library to our own WebApi. I have read about the Azure Hybrid Connection possibility, but our data still conveying through Microsoft servers might not be a possibility. So, my question is this:
Is there a way to configure the Microsoft.WindowsAzure.MobileServices Client library to point directly to our intranet, RESTful WebApi backend, without going through any Microsoft Azure servers ?
I understand that, in order to be able to use the Client librairies seamlessly, we probably would have to adapt our WebApi to implement the necessary .net Backend interfaces. I'm mostly wondering if it's even possible as the MSDN documentation on the libraries all seem to point to direct connections to their servers (no possibilities to configure your own connection strings) and all instructions redirect you to their Azure Mobile Services website.
Thank you.
If you look at the API for your mobile client, you'll notice that the Azure Mobile Services Client SDK only cares about two things:
new AzureMobileClient( url, appkey)
...where it's hosted shouldn't be a concern. Everything else is just configuration.
If you want to host the Azure Mobile Services Backend on your own servers, technically you could do this, but there are likely a few caveats. Microsoft has announced that they will be launching a Canadian Azure data center, but we won't see it until 2016.
In the meantime, here's how you can host the services locally. Note that I have not tried to emulate all of the features of Azure Mobile Services (aka Zumo) so your mileage (or kilometerage) will vary.
Hosting Locally:
From a technical feasibility, you absolutely can run the services locally. I know this because you can create the Azure Mobile Services Backend project from within Visual Studio and run it locally for development purposes. This is what our development team does for testing their mobile applications.
Note that you can create the Azure Mobile Service backend directly from within Visual Studio: New Project -> Cloud -> Azure Mobile Service. You can also download the exact same template (pre-configured with your URL and ApplicationKey) directly from the Azure dashboard: Create -> Mobile Service.
Obviously, if you're hosting it on your server it will be up to you to configure and use a proper SSL certificate for your site.
ZUMO Permissions:
By default, the security roles on the server are turned off. So if you're locking down any of your methods using the [AuthorizeLevel] attribute these settings will be ignored at runtime. If you need to enable this feature you can do so by modifying the WebApiConfig.Register() method and marking the site as self-hosted: config.SetSelfHosted(true).
Configuration:
From a configuration perspective, the Azure Mobile Service dashboard provides several tabs for configuring Identity, Push Notifications, Connection Strings and App Settings. Sadly, you won't have a dashboard, but all of these settings have a corresponding value in the local web.config. Any value you provide here is automatically overwritten in Azure, but they're used when running locally.
The minimum settings you'll need to configure are listed here. The ApplicationKey you can distribute with your ZuMo client, but the MasterKey is for the Admin authorization level so you'll want to keep that secret. The MobileServiceName is used by the EntityFramework for your database schema and what appears in the URL of your site.
<add key="MS_MobileServiceName" value="myzumosite" />
<add key="MS_MasterKey" value="masterkey" />
<add key="MS_ApplicationKey" value="appkey" />
Values that start with a MS_ prefix map to corresponding values in the Azure Portal. MS_GoogleClientID and MS_GoogleClientSecret map to the Google Identity values in the dashboard, for example.
Any other value in the AppSettings node is immediately accessible via the ApiServices.Settings property and corresponds to the Settings node in the Azure dashboard.
Database connection strings continue to exist in the connectionStrings node. The same is true for azure notification hub.
Database:
Obviously, the database you configure will be up to you as well. Permissions and User accounts are also obvious. There may be some minor differences between the SQL Azure syntax for Entity Framework database migration scripts that you'll need to worry about. (I've discovered the database migration scripts don't work from the Package Manager, but they do work when the database scripts are run when your website starts)
Caveats:
You will not have a nice dashboard for monitoring performance of your site, reviewing logs or changing runtime settings
You will not be able to scale out your site immediately; Scaling and deployment will be your problem
Deployment configuration is your responsibility (Project -> Publish won't be available unless you configure it)
Not sure if you'll be able to use Azure Active Directory as an authentication scheme, though from the sounds of it that won't be a concern. You can write your own authentication providers: Microsoft's Zumo library only supports a handful, but the underlying Owin.Security package that Microsoft uses supports several dozen systems!
Your site will need to be publically visible to your mobile clients
Push Notifications should work, but you will be using Azure's notification hub for this.
I have no idea where ApiServices.Log will go
The easiest path to take would be to:
Create the Mobile Service in Azure to get the notification hub and settings preconfigured
Download the starter site from the dashboard
Configure the web.config as mentioned here.
It's not possible to simply configure WAMS Client library to work with your own WebApi Backend.
But WAMS library is available at github, so I'm sure you can reuse a lot of code from the WAMS project, especially if you want to use a PCL project.
To route your data securly through Azure, you could think about setting up express route. Additionally, for last weeks update, it's possible to apply a custom domain to the WAMS Backend, including your own certificate to secure your connection.

Is it possible to update configuration settings programmatically?

We are experimenting with deploying an MVC app as an Azure web role. Currently the app is being hosted locally on our server. It has a few appSettings in Web.Config that can be changed by the users as part of the "Administration" module of the application.
I know this isn't a good practice for Azure because there will potentially be multiple instances of the application running with multiple Web.Configs, which makes updating them all a nightmare (if not impossible). My understanding is that the ConfigurationSettings specified in the service definition should be used instead of Web.Config so that settings are defined globally in one place that all the instances of the application can access.
My question is is it possible to programmatically update ConfigurationSettings similar to the way we update Web.Config settings, or would it be better for us to move those settings into a database or something else?
Yes, but unfortunately it is definitely not simple to do.
Follow this URL: http://msdn.microsoft.com/en-us/library/windowsazure/ee460809.aspx
It talks about a Svc Management API call that you can make to read/write the Service Configuration. It is a 64-base string which you'll need to decode, find XML flags in it that you want to change and re-encode it back and send it back to the API.
Not pleasant, but doable.

Unique account manager

I've got three different apps, all in GWT, none using Spring. Today, all of them got their own security layer provided by Tomcat. I want to setup a security layer shared by all of them. So that I don't have to deal with changes in the security layer for every app (following the DRY principle). I believe it's something similar to what Google does. Every time I try to login to any Google app, I'm taken to account.google.com.
How can I do that? Maybe setting this webapp Accounts to deal with every aspect of the accounts (log in and out, edit account, etc), and connect the session (or authentication) to my webapps?
You could deploy a Central Authentication Service and use it as an authentication provider for your applications.
Using a library (for example gwt-cas) to call your CAS will reduce your code duplication to a few lines of configuration per project.
You'll want to look into container-managed security. Here's the salient documentation.

Resources