Sharepoint authentication using javascript Rest api or jquery - javascript

I am just developing an sharepoint application in mobile by using javascript, But dont know how to start. Is there any api in javascript(jquery) to authenticate in sharepoint and get user details.
Thanks in advance.

For developing web applications in SharePoint 2013 and Online you have 2 main options for querying data from lists, libraries or users details, The Client Object Model and the SharePoint REST API.
Here is an example of updating list data using the Client object model
ClientContext context = new ClientContext("http://SiteUrl");
List announcementsList = context.Web.Lists.GetByTitle("Announcements");
ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
ListItem newItem = announcementsList.AddItem(itemCreateInfo);
newItem["Title"] = "My New Item!";
newItem["Body"] = "Hello World!";
newItem.Update();
context.ExecuteQuery();
Another option, which is preferred is to use the REST API to query endpoints. There are a number of APIs you can query in SharePoint, the most useful will be the Search API or the Social API, User Profile API, etc...
Here is an example endpoint you could query to retrieve JSON data, you can put it in the browser or post to the url to see what is returned.
http://<siteCollection>/<site>/_api/social.feed/my/feed/post
Here is an example of getting user profile data for the current user in SharePoint
$(document).ready(function(){
// Ensure the SP.UserProfiles.js file is loaded
SP.SOD.executeOrDelayUntilScriptLoaded(loadUserData, 'SP.UserProfiles.js');
});
var userProfileProperties;
function loadUserData(){
var clientContext = new SP.ClientContext.get_current();
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
//Get properties of the current user
userProfileProperties = peopleManager.getMyProperties()
clientContext.load(userProfileProperties);
clientContext.executeQueryAsync(onSuccess, onFail);
}
function onSuccess() {
console.log(userProfileProperties.get_displayName());
}
function onFail(sender, args) {
console.log("Error: " + args.get_message());
}

Related

Should I use an OData server or a custom XSJS service implemenation?

We are on a SAP HCP. For our application we need to provide a Web API.
We are unsure wheather to use an OData Service or a custom XSJS service implementation for this.
A few things we need to accomplish. All items also need to do a certain user authorization.
Select data from the database
Writing data into the database
Providing API functions that don't perfrom CRUD operations on the database, but for example send data to another server in the background
In my understanding an OData service would only fit the first two items, but does not provide a way to do anything that is not database (CRUD) related. Is this correct?
Are there any best practices for this scenario? Any suggestions and pointings in the right direction are welcome.
XSOData would no be able to perform non CRUD operations. With XSJS you can achieve this. I have done all of the three requirements on an on-premise
system & the same concepts should apply to HCP as well.
Sample code for executing a query & displaying data :
var queryString = "SELECT * FROM Table";
var connection = $.db.getConnection(); // DB Connection
var stmt = connection.prepareStatement(queryString);
var rs = stmt.executeQuery();
var output = "";
while (rs.next()) // Column setting
{
output += ("Col1:"+rs.getString(0)+", Col2:"+rs.getString(1)+";";
}
$.response.setBody(output);
To check for any GET or POST request & request parameters you can use $.request. With these you can perform your CRUD operations
You can refer to the XSJS API Reference for more info
http://help.sap.com/hana/SAP_HANA_XS_JavaScript_API_Reference_en/
For sending data to another server, one way would be by providing a web service from the second server. XSJS can make Web Request to a configured destination so you can POST data to your server. You will need to create a destination file(.xshttpdest) for accessing you server
Some sample Code:
var dest = $.net.http.readDestination("<package path to destination file>", "<destination file name>");
var client = new $.net.http.Client();
var req = new $.web.WebRequest($.net.http.POST, "/");
req.contentType = "application/json";
req.setBody("My data");
client.request(req, dest);
var response = client.getResponse();
You can find details on the below link to create a HTTP Destination & send data https://help.hana.ondemand.com/help/frameset.htm?06ca24043b0f4eb78cf39c6bc1d8a8dc.html

Creating LinkedNotebooks from API

I am working with the Evernote api trying to make linked notebooks from within our web application.
We are using evernote-sdk-js version of the API.
We are able to create the Shared Notebook from the API. Also we are able to create a Linked Notebook and receive a valid response. The problem is the linked notebook is not working. The notebook is returned in the ListLinkedNotebook api call but when I try to authorize it I receive an error.
Error { identifier: 'SharedNotebook.id', key: 'xxxx' }
From what I've read means the notebook is no longer shared by the owner. This is not true as the owner account still shows the pending request in the 'share' window.
Here is the logical flow:
1) User enters email address of the person they wish to share notebook with. A request is made to our server to create a ShareNotebook.
We create a Shared Notebook like this: (From Owner Account)
var notebook = new Evernote.SharedNotebook();
notebook.notebookGuid = guid;
notebook.email = email;
notebook.privilege = Evernote.SharedNotebookPrivilegeLevel.FULL_ACCESS;
var userclient = new Evernote.Client({token: token, sandbox: sandbox});
var notestore = userclient.getNoteStore();
notestore.createSharedNotebook(userclient.token, notebook, function(err, results){
callback(err, results);
});
With an example response like:
{
allowPreview:null
email:"...#gmail.com"
id:12345
notebookGuid:"d2fa3cbe-...."
notebookModifiable:false
privilege:4
recipientSettings:null
requireLogin:null
serviceCreated:1469079222000
serviceUpdated:1469079222000
shareKey:"xxxx-sxxx"
userId:999xxxxx
username:null
}
2) Since Evernote doesn't send an email from the API request we manually send the user a link to activate the Shared Notebook.
Code to create LinkedNotebook: (From Shared User Account)
var notebook = new Evernote.LinkedNotebook;
notebook.shareName = options.shareName;
notebook.username = options.username;
notebook.shardId = options.shardId;
notebook.shareKey = options.shareKey;
var userclient = new Evernote.Client({token: token, sandbox: sandbox});
var notestore = userclient.getNoteStore();
notestore.createLinkedNotebook(userclient.token, notebook, function(err, results){
callback(err, results);
});
And the example response:
{
shareName: 'Notebook Name',
username: '...',
shardId: 'sxxx',
shareKey: 'xxxx-sxxx',
uri: null,
guid: '4f8df3c2-...',
updateSequenceNum: 630,
noteStoreUrl: 'https://www.evernote.com/shard/sxxx/notestore',
webApiUrlPrefix: 'https://www.evernote.com/shard/sxxx/',
stack: null,
businessId: null
}
Has anyone had any luck creating a Linked Notebook from the API? It seems like the createLinkedNotebook API call is not working correctly. Thanks for your help.
tl;dr you can't do what you're trying to do right now, sorry.
So there are a couple pieces missing here, not something you can do much about.
The first piece is that the shared notebook must be "claimed" by a user (the recipient), during which it gets assigned to the user. Until it's claimed, a LinkedNotebook pointing to the SharedNotebook won't actually give you access to the underlying Notebook - authenticateToSharedNotebook will fail.
The second piece is the shareKey itself. We renamed the struct member you see as shareKey to globalId on the SharedNotebook and sharedNotebookGlobalId on the LinkedNotebook - we're currently in the process of updating our developer documentation, and then we'll update the sdks. To "claim" a sharedNotebook, the recipient needs to call authenticateToSharedNotebook with the shareKey, not the globalId. The catch is that we don't expose a method to generate the real shareKey, so there's no way for third-party clients to generate this and join the shared notebook. Once it is claimed, you can call authenticateToSharedNotebook with the globalId to get access to the notebook.
There's a shareNotebook method we added that send an email as part of the API call. That email contains a link for the user to click on which contains the shareKey and allows claiming a SharedNotebook, but that isn't currently in the SDKs or documented. We'll hopefully get it up with this round of doc updates.

SignalR service: Get message depending on user role

I created
MVC app (installed -Install-Package Microsoft.AspNet.SignalR.JS) (ref here)
Web Service
(//Install from Nuget Package window
//Install-Package Microsoft ASP.NET SignalR .NET Client
//Install-Package Microsoft ASP.NET SignalR Core Components)
Signalr Service (Installed -Install-Package Microsoft.AspNet.SignalR.SelfHost and Install-Package Microsoft.Owin.Cors)
What I am doing: I am calling MVC page and after processing one task using web service. In that web service when task is processing I want to notify user what is going on behind the seen like task is in processing or it is done using Signalr service.
I created All project separately.
using web Service I am calling the signalr hubs (see here)
challenges facing:
I want to broadcast the message to that user and if no. of user are there then depending on there role i want to send messages.
Edited:Extra Enhancement added in my project:I have no. of MVC app and its corresponding Web services and My single signalR service so how can I identify which MVC app calling it corresponding service and service pushing to all or it application users or particular user. Like pusher will create application Id to application and number of tokens for user. It is possible to do it.
Summary:
I'm not sure that it's possible to have the hubs living on the WCF SignalR service. It would be best to let the MVC project act as a proxy between the client and web service. You can connect to SignalR later with other clients (such as desktop clients) if that's one of your requirements, and also connect to this hub from your web service to send updates to the clients and/or users in a specified group.
Workflow:
To start, the flow would look more like this:
Managing Client Connections:
If you are using an in-memory approach to managing your connected users, then you could start by adding the connection id and the user id to whatever collection you are using to handle this. For example:
public static ConcurrentDictionary<String, String> UsersOnline = new ConcurrentDictionary<String, String>();
public override System.Threading.Tasks.Task OnConnected()
{
UsersOnline.TryAdd(Context.ConnectionId, Context.User.Identity.GetUserId());
return base.OnConnected();
}
A word of caution: The Context.User will be null unless you map SignalR after the authentication.
It may be beneficial to store the connection id in variable on the client side as well so you can pass it to your methods later.
var connectionId;
var testHub = $.connection.testHub;
$.connection.hub.start().done(function () {
connectionId = $.connection.hub.id;
}
The Hub:
The hub can be used to communicate with the web service. In this example I'll be using it as a soap service, but rest should work just the same.
public void LongRunningTask(String ConnectionId)
{
using (var svc = new Services.MyWebService.SignalRTestServiceClient())
{
svc.LongRunningTask(ConnectionId);
} // end using
} // end LongRunningTask
Note that we pass the connection id to the service as well. This comes into play when the service starts sending messages back to the MVC project to deliver to the client(s).
Listener or Web API:
Set up a listener controller or a Web API on the MVC site to receive messages from the web service.
public ActionResult SignalR(String Message, String Type, String ConnectionId)
{
if (!String.IsNullOrWhiteSpace(Message) && !String.IsNullOrWhiteSpace(Type) && !String.IsNullOrWhiteSpace(ConnectionId))
{
if (Type == "ShowAlert")
{
// Determine if the user that started the process is still online
bool UserIsOnline = Hubs.TestHub.UsersOnline.ContainsKey(ConnectionId);
// We need this to execute our client methods
IHubContext TestHub = GlobalHost.ConnectionManager.GetHubContext<Hubs.TestHub>();
if (UserIsOnline)
{
// Show the alert to only the client that started the process.
TestHub.Clients.Client(ConnectionId).showAlert(Message);
} // end if
else
{
List<String> UserIdsInRole = new List<String>();
using (var connection = new System.Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString()))
{
// Assuming you're using Identity framework since it is an MVC project, get all the ids for users in a given role.
// This is using Dapper
UserIdsInRole = connection.Query<String>(#"
SELECT ur.UserId
FROM AspNetUserRoles ur
JOIN AspNetRoles r ON ur.RoleId = r.Id
WHERE r.Name = #rolename
", new { rolename = "SpecialRole" }).ToList();
} // end using
// Find what users from that role are currently connected
List<String> ActiveUsersInRoleConnectionIds = Hubs.TestHub.UsersOnline.Where(x => UserIdsInRole.Contains(x.Value)).Select(y => y.Key).ToList();
// Send the message to the users in that role who are currently connected
TestHub.Clients.Clients(ActiveUsersInRoleConnectionIds).showAlert(Message);
} // end else (user is not online)
} // end if type show alert
} // end if nothing is null or whitespace
return new HttpStatusCodeResult(200);
} // end SignalR
Web Service:
The web service method that does the long running work should accept a client id as well, so it can send it back to the listener controller or web API. It can use a method similar to this (using RestSharp) to connect back to the MVC project:
public void ShowAlert(String Message, String ConnectionId)
{
RestClient Client = new RestClient("http://localhost:8888");
RestRequest Request = new RestRequest("/Listener/SignalR", Method.POST);
Request.Parameters.Add(new Parameter() { Name = "Message", Type = ParameterType.QueryString, Value = Message });
Request.Parameters.Add(new Parameter() { Name = "Type", Type = ParameterType.QueryString, Value = "ShowAlert" });
Request.Parameters.Add(new Parameter() { Name = "ConnectionId", Type = ParameterType.QueryString, Value = ConnectionId });
IRestResponse Response = Client.Execute(Request);
} // end Show Alert
Demo:
I did a proof of concept and uploaded it to Github.

Creating a YouTube Service via ASP.NET using a pre-existing Access Token

I've been working on a Website for users to upload videos to a shared YouTube account for later access. After much work I've been able to get an Active Token, and viable Refresh Token.
However, the code to initialize the YouTubeService object looks like this:
UserCredential credential;
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
// This OAuth 2.0 access scope allows an application to upload files to the
// authenticated user's YouTube channel, but doesn't allow other types of access.
new[] { YouTubeService.Scope.YoutubeUpload },
"user",
CancellationToken.None
);
}
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = Assembly.GetExecutingAssembly().GetName().Name,
});
I've already got a token, and I want to use mine. I'm using ASP.NET version 3.5, and so I can't do an async call anyways.
Is there any way I can create a YouTubeService object without the async call, and using my own token? Is there a way I can build a credential object without the Authorization Broker?
Alternatively, the application used YouTube API V2 for quite some time, and had a form that took a token, and did a post action against a YouTube URI that was generated alongside the token in API V2. Is there a way I can implement that with V3? Is there a way to use Javascript to upload videos, and possibly an example that I could use in my code?
NOTE: I ended up upgrading my Framework to 4.5 to access the google libraries.
To programatically initialize a UserCredential Object you've got to build a Flow, and TokenResponse. A Flow Requires a Scope (aka the permissions we are seeking for the credentials.
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Responses;
using Google.Apis.Auth.OAuth2.Flows;
string[] scopes = new string[] {
YouTubeService.Scope.Youtube,
YouTubeService.Scope.YoutubeUpload
};
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = XXXXXXXXXX, <- Put your own values here
ClientSecret = XXXXXXXXXX <- Put your own values here
},
Scopes = scopes,
DataStore = new FileDataStore("Store")
});
TokenResponse token = new TokenResponse {
AccessToken = lblActiveToken.Text,
RefreshToken = lblRefreshToken.Text
};
UserCredential credential = new UserCredential(flow, Environment.UserName, token);
Hope that helps.
Currently the official Google .NET client library does not work with .NET Framework 3.5. (Note: this is an old question the library hasn't supported .NET 3.5 since 2014. So the statement would have been valid then as well.) That being said you are not going to be able to create a service for the Google .NET client library using an existing access token. Also not possible to create it with an access token using any .NET Framework you would need to create your own implementation of Idatastore and load a refresh token.
Supported Platforms
.NET Framework 4.5 and 4.6
.NET Core (via netstandard1.3 support)
Windows 8 Apps
Windows Phone 8 and 8.1
Portable Class Libraries
That being said you are going to have to code this yourself from the ground up. I have done it and it is doable.
Authentication :
You have stated you have your refresh token already so I won't go into how to create that.
The following is a HTTP POST call
Refresh access token request:
https://accounts.google.com/o/oauth2/token
client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&refresh_token=1/ffYmfI0sjR54Ft9oupubLzrJhD1hZS5tWQcyAvNECCA&grant_type=refresh_token
Refresh Access token response:
{ "access_token" : "ya29.1.AADtN_XK16As2ZHlScqOxGtntIlevNcasMSPwGiE3pe5ANZfrmJTcsI3ZtAjv4sDrPDRnQ", "token_type" : "Bearer", "expires_in" : 3600 }
An call you make to the YouTube API you can either add the access token as the authorization bearer token or you can just take it on to the end of any request
https://www.googleapis.com/youtube/v3/search?access_token={token here}
I have a full post on all of the calls to the auth server Google 3 legged Oauth2 flow. I just use normal webRequets for all my calls.
// Create a request for the URL.
WebRequest request = WebRequest.Create("http://www.contoso.com/default.html");
// If required by the server, set the credentials.
request.Credentials = CredentialCache.DefaultCredentials;
// Get the response.
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine (((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams and the response.
reader.Close();
response.Close();
Upgrade .NET 4+
If you can upgrade to the newest version of .NET using the library will be much easier. This is from Googles official documentation Web Applications ASP.NET. I have some additional sample code on my github account which shoes how to use the Google Drive API. Google dotnet samples YouTube data v3.
using System;
using System.Web.Mvc;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Mvc;
using Google.Apis.Drive.v2;
using Google.Apis.Util.Store;
namespace Google.Apis.Sample.MVC4
{
public class AppFlowMetadata : FlowMetadata
{
private static readonly IAuthorizationCodeFlow flow =
new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = "PUT_CLIENT_ID_HERE",
ClientSecret = "PUT_CLIENT_SECRET_HERE"
},
Scopes = new[] { DriveService.Scope.Drive },
DataStore = new FileDataStore("Drive.Api.Auth.Store")
});
public override string GetUserId(Controller controller)
{
// In this sample we use the session to store the user identifiers.
// That's not the best practice, because you should have a logic to identify
// a user. You might want to use "OpenID Connect".
// You can read more about the protocol in the following link:
// https://developers.google.com/accounts/docs/OAuth2Login.
var user = controller.Session["user"];
if (user == null)
{
user = Guid.NewGuid();
controller.Session["user"] = user;
}
return user.ToString();
}
public override IAuthorizationCodeFlow Flow
{
get { return flow; }
}
}
}
Top tip YouTube doesn't support service accounts your going to have to stick with Oauth2. As long as you have authenticated your code once it should continue to work.

node.js - how to switch a database in mongodb driver?

I'm new to this stuff and just stuck in the middle of nowhere. Am using node-mongodb-native and am in need to switch to another database (after authentication against admin db). I googled and found this topic where the creator of library recommends to keep a connection for each db in a hash. So my question is - how do I accomplish it?
Just create different database connections and store them in an object.
var dbConnections = {};
var dbConnections.authDb = new Db('adminDb', server, {});
dbConnections.authDb.authenticate(username, password);
var dbConnections.otherDb = new Db('otherDb', server, {});
Does that make sense?
There's an example hidden in the MongoDB driver docs under Db:
[...]
MongoClient.connect('mongodb://localhost:27017/test', function(err, db) {
[...]
// Reference a different database sharing the same connections
// for the data transfer
var secondDb = db.db("integration_tests_2");
// Fetch the collections
var multipleColl1 = db.collection("multiple_db_instances");
var multipleColl2 = secondDb.collection("multiple_db_instances");
[...]
});

Categories