How to access Rich Text Field Image outside SalesForce? - node.js

I'm using SalesForce object to store user information, it includes profile image too. I'm able to insert images in Rich Text Field by sending Base64 String along with <img> tag. Image gets stored and displayed in the SalesForce page. No problem with that.
Also I'm able to get the image url to the client side (Mobile App) with the help of Rest API (NodeJS).The problem here is, Image URL is accessible(browser) only if the SalesForce account is logged in. If else it goes to the SalesForce login page (When I try with other brower).
What I want is to display the images in my Mobile app which doesn't have SalesForce login access. But I can provide enough information to client side if needed.
My image url looks like this,
https://c.ap5.content.force.com/servlet/rtaImage?eid=a037F00000YSybT&feoid=00N7F00000Pupl6&refid=0EM7F000000lIN0
Also, I have some of the security information in my server side (Node) which I got when I successfully login to SalesForce. BTW I'm using node-salesforce package to establish SalesForce connection.
1) organizationId
2) instanceUrl
3) userID
4) accessToken
I have been stuck with this problem since a week before and I'm running out of deadline. Please HELP!!!
Thanks!

I ended up rewriting the urls in the rich text on the fly when returning them from my api. In a manner so that they refer to my api which I use as image proxy through this SF API endpoint with an integration user: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_sobject_rich_text_image_retrieve.htm
private void rewriteImageUrls(RichTextRecord richTextRecord) {
Document doc = Jsoup.parse(richTextRecord.getBody());
doc.select("img").forEach(imgElement -> {
try {
URL originalUrl = new URL(imgElement.absUrl("src"));
String newUrl = appEnv.getBackendUrl() + "/api/v1/rich_text_records/" + richTextRecord.getSfid() + "/image?refid="+ UrlUtils.getQueryMap(originalUrl.getQuery()).get("refid");
imgElement.attr("src", newUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
});
richTextRecord.setBody(doc.outerHtml());
}
Far from ideal but it works!

Related

Docusign return parameters in embedded signing by breaking out iframe

How to pass parameters(envelope,PF and r ID) within iframe while returning URL in embedded docusigning? If I enter the POWERFORM link on browser I'm returning URL with the parameters (envelope,PF and r ID) but if I run code within iframe I'm unable to get the parameters. Please do assist me about this issue.
You are opening Powerform inside an IFrame, so the scope of the opened URL is inside the IFrame only and DocuSign cannot do anything to redirect the browser to come out of the IFrame. You have write a code on your end to capture the redirect URL and break the flow out of IFrame, you can find a similar query here. Normally DocuSign does not recommend using IFrame for Signing, also to capture the data like envelopeId, r Id etc, it is better to configure DocuSign Connect with a listener on your side. Using url redirect is a fragile solution as user might close the browser (or browser hangs/network issue) and you might lose the data. Whereas with DS Connect, DocuSign will publish the event to your listener and you will be able to capture all the required data in your listener.
<script>
function myFunction()
{
var x = document.getElementById("form1").action;
document.getElementById("demo").innerHTML = x;
}
</script>
This thing works for displaying the parameters.
window.parent.window.location.href = 'Parent URL' works to break out of an iframe and load the parent page.

Password type field in gmail card service

Right now, in gmail appscript we don't have any option to add a password type field.
Gmail Card Service for add-on has a very good ability to show any thing in it. We can integrate with any app which has basic REST api. We need authentication for that which commonly need password type field.
Any work around to show password type field?
As of now, there is no support for password field in Gmail add-on.
But we can build a hack for it. I hope password is needed only in registration forms. So, we can build a registration form using HTML and that can be served through authorization action.
CardService.newAuthorizationAction().setAuthorizationUrl(loginUrl)
Here, host registration HTML in a web server and pass this URL as "loginUrl" in the above snippet. We have to supply AuthorizationAction for the signup/register button. So, when the user clicks on this button, a new popup page is launched, the user will give the username, password, etc... onsubmit, we can encode all the form data and pass it to the parent Gmail add-on by redirecting it to a script redirection URL which you can generate an add-on. Once the redirection to the script URL comes, there will be a callback in our add-on code from there you can get the form fields which were encoded from registration HTML page.
function generateNewStateToken(callbackName, payload) {
return ScriptApp.newStateToken()
.withMethod(callbackName)
.withArgument("payload", JSON.stringify(payload))
.withTimeout(3600)
.createToken();
}
function getRedirectURI() {
return "https://script.google.com/macros/d/" + ScriptApp.getScriptId() + "/usercallback";
}
var state = generateNewStateToken("registerCallback", {"signup": true});
var reg_url = <reg_url> + "?redirect_uri=" + getRedirectURI() + "&state=" + state;
function registerCallback(cbResp) {
// to access payload which passed in state token: cbResp.parameter.payload;
// in the html serialize all the form fields or data which you want to pass to plugin as query params like: <redirect_uri>?form_data=<encoded_data>&state=<state>
//Note: here the registration HTML page should parse the URL to get the state & redirect_uri from URL.
// to access form_data: cbResp.parameter.form_data
}
I hope this will help you. This is how we are doing the signup/signin flow now.
Looks like you are authorizing a non google service . Please refer to Authorizing custom google services .

Download and display images from sharepoint (Xamarin.Forms PCL)

I'm currently developping an app based on Sharepoint REST API and Microsoft Graph. My app is composed mainly with a Tabbed Page, and on the first tab I want to display News from sharepoint. To do so I want to get images from the news, but using the url of the images as Image Source returns me "forbidden" error. So, I decided to find a way to download those images. I've been looking for a way for few days now, and found nothing...
Does anyone knows a way to do that, or why do I have a forbidden access error ?
I bring some precisions, I'm using an HttpClient to authenticate to the tenant with REST API :
client = new HttpClient();
Uri mUri = new Uri(App.ReturnUri);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var data = await DependencyService.Get<IAuthenticator>()
.Authenticate(App.LoginAuthority, App.RestResourceUri, App.ClientId, mUri);
App.AuthenticationResult = data;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", App.AuthenticationResult.AccessToken);
From that, I hope someone knows if there is a way to download images, or to access to url in order to use them as Source. I succeeded in retrieving URLs but not displaying images, knowing that I can retrieve any other data from sharepoint
Thanks for any help,
The Image component can use a URL as its data, but that requires images that aren't behind an authentication which is probably the case with your SharePoint images. That is also why it's returning you a Forbidden error.
var webImage = new Image { Aspect = Aspect.AspectFit };
webImage.Source = ImageSource.FromUri(new Uri("https://xamarin.com/content/images/pages/forms/example-app.png"));
To add the authentication layer for SharePoint you would probably be able to implement your own UriImageSource implementation. In the end an ImageSource only needs a Stream object so getting that from either the internet or local storage would work.
To download and store images you will have to write code for both platforms specifically because local storage works differently. Check out this blog post as a starting point combined with your own piece of code.
https://blog.falafel.com/xamarin-forms-storing-and-retrieving-photos/

WebClient with credentials still not downloading file

I am trying to download files from a website with username/password. You need to pay for a registered account in order to download files - which we have done. I am attempting to pass in the username/password and download a file as follows:
if (docUrl != null)
{
if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
this.WebClientInstance.Credentials = new NetworkCredential(username, password);
fileData = this.WebClientInstance.DownloadData(docUrl);
this.WebClientInstance.Dispose();
isDataDownloaded = true;
}
WebClientInstance is a System.Net.WebClient. I debugged and verified that it is hitting the line to set credentials. Instead of downloading the PDF, I end up with an HTML page that prompts me to log in to get access to the file. I have verified that the username/password is correct. I use the same credentials to scrape the website with WatiN.
Is there something else that I'm supposed to be doing here?
UPDATE
Okay, I've done some sniffing around and found some useful info on this issue. I still haven't gotten it to work, but I think I'm closer. First, you need to create a cookie aware WebClient that extends the WebClient class, as follows:
public class CookiesAwareWebClient : WebClient
{
public CookieContainer CookieContainer { get; private set; }
public CookiesAwareWebClient()
{
this.CookieContainer = new CookieContainer();
}
protected override WebRequest GetWebRequest(Uri address)
{
var webRequest = base.GetWebRequest(address);
if (webRequest is HttpWebRequest)
(webRequest as HttpWebRequest).CookieContainer = this.CookieContainer;
return webRequest;
}
}
Next is to use the WebClient.UploadValues() method to upload the login info to the target website. The full process of authenticating and downloading the target resource is as follows:
using (var webClient = new CookiesAwareWebClient())
{
var postData = new NameValueCollection()
{
{ "userId", username },
{ "password", password }
};
webClient.UploadValues(docUrl, postData);
fileData = webClient.DownloadData(docUrl);
}
I was wrong about the site using forms auth. It is a JSP website and uses a JSESSIONID. I have verified that I am getting a cookie back with what appears to be a valid 32-byte JSESSIONID value.
However, when I call WebClient.DownloadData() it is still only returning the redirected login page. I've tried to fix this by setting the AllowAutoRedirect property on the HttpWebRequest to false, but then it returns 0 bytes.
Is there something else that I need to do so it won't redirect and will take me to the resource once I have authenticated?
(Answered in a question edit. Converted to a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
Solved. So the problem was between my ears. I was passing in the URL for the secure resource to the .UploadValues() method, knowing that it would redirect to the login page. However, I really needed to pass in the URL from the login form (where it goes upon submitting) - not the login page itself. Once I did that, it worked correctly. I think I'm going to go find a career in food service now.
LINKS
There were already a few questions posted on SO that addressed this issue. I just didn't know what I was looking for at first so I didn't see those... Anywhere here are a couple good resources that I came across when working on this issue:
how to maintaine cookies in between two Url's in asp.net
Trying to get authentication cookie(s) using HttpWebRequest

How to provide information in the html link for Facebook open graph api call of "property name" when posting trying to post an action

I am trying to create an html object dynamically with the necessary header information depending on the query string in the link I provide to Facebook. I am hoping that Facebook open graph will call this html link as I provided. However it seems that query string info are not getting passed to my server. Do anyone know how to make this work or what is the more appropriate way to do this. BTW, I am writing my code in Node.js.
To get more info about Facebook open graph api, look here, https://developers.facebook.com/docs/beta/opengraph/actions/.
For example, the link I am trying to pass to Facebook is, "http://xxx-url.com/getFacebookObject?objectId=&description=first dynamic post", so I sent a request with the link as, "https://graph.facebook.com/me/app-name:action-name?object=http://xxx-url.com/getFacebookObject?objectId=&description=first dynamic post". However, when I check the log on the server, I don't see anything in the query string.
Instead of using the query string, you can embed the data in the URL:
http://some-domain.com/getFacebookObject/id/description
Then, depending on what node.js packages you're using, extract the data from the request:
// expess.js style
app.get("/getFacebookObject/:id/:description", function(req, res) {
var id = req.params.id,
desc = req.params.description;
// your code...
});
(See http://expressjs.com/guide.html.)
Sorry, Facebook will strip off all query string information from the URL when they launch your site in the iframe. If it was a page tab app, then you could add it to the app_data query string parameters which in turn gets passed to your iframe's page tab app via the app_data part of the signed_request parameter.

Resources