Post by: Oliver Wirkus
Posted on: 10/22/2015 6:38:00 PM
I recently was faced with the task to create a SharePoint Add-In (formerly known as 'App'), that retrieves all tasks of a user. I have done this many times before and my approach usually has been to use the
KeywordQuery object to retrieve the task items from SharePoint search. This apporach (usually referred to as Search Driven Application) used to work well - in the old server-side-code environment! But times have changed and today, SharePoint development is switching from server-side code to client-side code - it is switching from SharePoint web parts to SharePoint Add-Ins. It's obvious that you can't use the old KeywordQuery object to create a SharePoint Add-In that is executed client-side. Luckily Microsoft is providing the
// Remember to change settings in search. Make 'PercentCompleteOWSNMB' are queryable property function handleQuery()
// Build the query var keywordQuery = new Microsoft.SharePoint.Client.Search.Query.KeywordQuery(context); var queryText = "(ContentClassSTS_ListItem_Tasks)"; queryText += " AND (AssignedTo'" + user.get_title() + "')"; queryText += " AND (PercentCompleteOWSNMBR<>'1')";
//Assign the query keywordQuery.set_queryText(queryText);
// Add a row limit (retrieve only the first 10 items) keywordQuery.set_rowLimit("10");
// Add a sorting var sortList = keywordQuery.get_sortList(); sortList.add("LastModifiedTime", Microsoft.SharePoint.Client.Search.Query.SortDirection.descending);
// Add additional properties keywordQuery.get_selectProperties().add("PercentCompleteOWSNMBR");
// Execute the query var searchExecutor = new Microsoft.SharePoint.Client.Search.Query.SearchExecutor(context); queryResults = searchExecutor.executeQuery(keywordQuery); context.executeQueryAsync(onQuerySuccess, onQueryError);
function onQuerySuccess() $("#resultsDiv").append("<table>");
$.each(queryResults.m_value.ResultTables.ResultRows, function () $("#resultsDiv").append("<tr>"); $("#resultsDiv").append("<td>" + "<a href='" + this.Path + "'>" + this.Title + "</a>" + "</td>"); $("#resultsDiv").append("</tr>"); );
function onQueryError() $("#message").text("Query failed");
Post by: Oliver Wirkus
Posted on: 10/19/2015 3:26:00 PM
Categories: Business;Office 365;SharePoint
Description: There is a latent security issue in Delve in terms of permissions accidentially provided.
While the Microsoft SharePoint search engine is a very powerful tool, my attention is currently drawn towards Delve and Office Graph. Delve and Office Graph go hand-in-hand as Delve is the user-focus front end platform that visualizes data retrieved and sorted by Office Graph. Office Graph is the new and exciting search and index engine that uses artificial intelligence and fuzzy logic to create relations between data and persons while crawling data. While studying Office Graph I came across a latent security issue that Delve users should be aware of. To illustrate this latent security issue, let's do a little thought experiment. Let's assume there is a company using an intranet based on SharePoint Online as part of Office 365. This company is using SharePoint extensively resulting in a large structure of sites and subsites. Deeply hidden inside this subsite structure, another user grants you access to a document by accident that you should not have access to, because it is confidential. Although this is a major security risk, it may stay undiscovered for a long period of time with the way the current SharePoint Search index works. The current SharePoint Search index will index this document, its metadata and the security settings upon its next crawl and this data will be stored to the SharePoint search index as usual. Unless you aren't searching for this document (that you probably don't know of) actively, there is a good chance that you'll never discover that there is a confidential document hidden deeply inside the subsite structure you have access to. These kind of security risks will drastically change when Office Graph and Delve come into play. Of course, Office Graph will also find this document and it will add it to its internal database. In addition, Office Graph will create relations based on coworkers changes to the permissions and/or document body and it will create relations that connect you with them and will also weigh these relations internally. As an individual with accidental access to a confidential document on Delve, there is a good chance that you will discover this document very soon. As I mentioned at the beginning, Delve is not showing search results based on an active request of a user. As soon as a user is opening Delve, it shows what is currently trending around the user and if your colleagues are currently collaborating on this document, there is a good chance that Delve will show this document as one of the most important documents, because it appears to be very important for your coworkers – that's how weighted relations work! The same issue will occur if the document is saved to a file share that is crawled by SharePoint. Don't get me wrong, there is nothing wrong with Delve or Office Graph. It's just the different way search results will be displayed to a user - and we as users need to be aware of this! To prevent these kind of accidental security issues, there is an option besides switching Delve off for your tenant in the Office 365 Admin Center. You can selectively disable Delve from showing certain documents or data in the Delve search results. The only thing you need to do is to declare a site column named 'HideFromDelve' and to use it in lists or libraries to selectively exclude documents and data from being shown in the Delve search results. Mikael Svenson (MVP) explained this in detail in his post. If you want to know more, I encourage you to read his article. But you need to keep in mind that this only affects Delve as the front end of Office Graph. Third party applications that also use search results derived from Office Graph will most likely ignore this site column and this mechanism is not affecting Office Graph itself. Office Graph will still add data to its index despite using this site column. Disregarding this latent security issue, I still think that Office Graph is a great tool and it is an important step towards new search engines that rely on weighted relations to recognize metadata on their own. Who knows – maybe one day manual metadata entry will be relieved as a tedious task for users. The future remains exciting!Post by: Oliver Wirkus
Posted on: 10/8/2015 11:04:00 PM
Categories: Office 365;SharePoint
I have been promoting Document Management with SharePoint for many years now and I’m still convinced that enterprises will benefit a lot if they move their files from a file-share to SharePoint. Although managing files in SharePoint libraries usually solves a lot of problems enterprises encounter with saving their corporate files to file-shares, there are some issues that impact the user experience negatively. One of these issues has been the way employees access files if the files are moved to different locations. To understand this issue, we need to have a look at the Document Lifecycle first. Document Management is not only saving documents to SharePoint libraries instead of saving them to folders in a file-share. A Document Management System should at least support a basic document lifecycle. A document undergoes different stages during its lifetime. A typical document lifecycle could look like this, but there are also more extensive definitions
Let’s have a look at a common scenario to understand the basics of a document lifecycle. If an important document is created, usually a team is working on this document and this team usually is using a SharePoint team site to collaborate. As long as this document is saved to a document library that is part of this team site, everyone can access this document by its URL – assuming he or she has appropriate permissions. This is what the document lifecycle describes in its ‘Create’ phase.
When the work on this important document has been finished, it is usually reviewed by using an approval process based on a workflow. When the document is approved, it is usually saved to a different SharePoint library. This can be a library for official documents in a company. The document lifecycles refers to this as the ‘Distribute’ phase. It is obvious that this document can’t be accessed by its ‘old’ URL anymore, because it has been moved to a new library and because of that the ‘old’ URL gets invalid. Same is true for the additional steps of a basic document lifecycle. There is another scenario which leads to invalid document URLs. Sometimes it happens that a company decides to restructure their intranet. As soon as documents are moved to a new location, they can’t be accessed by their old URL anymore, because the URL changed because of the move. Same is true if the document is renamed. Let’s see how this looks like. The following screenshot shows a common document library in SharePoint 2016. I just added a new document to this library
To retrieve the URL of this document, we can simply click on the three ellipses. SharePoint 2016 will show a pop-up with the accounts that this document is shared with and it’s URL. The URL of my sample document is looking like this
If this document is moved to a new library, it can’t be retrieved by its URL anymore, because the name of the old library (“Shared Documents”) is part of the URL. Same is true if the document is moved to a different site, because the name of the site (“wirkus”) is also a part of the URL.
SharePoint provides a solution for this by leveraging Document IDs. In simple terms SharePoint is using an internal service to add a unique number to each newly created document. Because this service is running in the scope of a site collection, the IDs are unique only within the same site collection. To overcome this limitation, a custom Document ID provider can be created or a prefix can be configured. If you are interested in how to do this, I encourage you to have a look on this blog post I have published some months ago. Setting up Document IDs is very easy – you only need to activate the corresponding site collection feature
If you add a new document to a library with Document IDs turned on, SharePoint will assign a new Document ID to the document. The URL of the document is looking different now
http//sp2016b-mj/sites/wirkus/_layouts/15/DocIdRedir.aspx?ID=5QUY74FYUPFY-1778240737-2 As you can see, the URL of the document does not contain any document related information now – except of the Document ID. Instead it redirects to a SharePoint page (called DocIDRedir.aspx) and adds the Document ID of the document as a parameter. This page leverages a control that takes the given Document ID and looks for the document. Although this involves an additional step, a user usually does not recognize this additional step when accessing a document by its DocumentID-based URL. The creation of the Document IDs is managed by two different timer jobs just the same way it was in SharePoint 2013
Based on my findings using the current public beta of Microsoft SharePoint 2016 (Version 16.0.4316.1217), it looks like Microsoft just enhanced the Document ID services of SharePoint 2013 a little to make it more user-friendly. That's the reason why I assume, that this service is working in SharePoint 2016 almost the same way as it did in SharePoint 2013. To understand how this service is working internally, we should have a view on the code needed to create a custom Document ID provider. The
basic framework of a DocumentID provider looks like this
Each Document ID provider needs to expose a method that generates a new Document ID. This method is named
GenerateDocumentId(SPListItem item). It is called by passing one parameter only the SharePoint item that should get a new Document ID. The Document ID provider is creating a new Document ID and it internally joins it with the SPListItem it gets when the method
GenerateDocumentId()is called. That’s the reason why the Document ID provider is able to create an internal list of all the Document IDs it has created and their joined documents. The Document ID provider uses this internal list to retrieve documents based on their ID. To leverage that functionality, each Document ID provider exposes another method
GetDocumentUrlsById(SPSite site, string docID).
This method is called by SharePoint to retrieve a document by its DocumentID. Basically this is what the page DocIdRedir.aspx does. This method is called with the current site and the Document ID as parameters and it is supposed to return the URL of the joined document. If the document can’t be found in its internal list, each Document ID provider is using the SharePoint Search Index to retrieve the URL of the document. In the end this is the reason why SharePoint is able to retrieve a document by its Document ID even if this document has been moved to another site collection. Although a different Document ID provider is involved if the document has been moved from one site collection to another site collection (because a Document ID providers is site collection-scoped), this different provider can still use the SharePoint search to retrieve the document.
Based on the current beta version of SharePoint 2016 it appears, that Durable Links are the ‘old’ DocumentIDs with minor enhancements.