This repository contains examples showing how to use the PowerDMS File Picker. Currently only an ASP.NET Core example is provided.
For information about getting access to the PowerDMS File Picker, contact us at support@powerdms.com.
The PowerDMS File Picker is a file selection widget that can be embedded into any web application and to provide users the ability to search for and select files from PowerDMS.
It presents users with a familiar and consistent experience when accessing their PowerDMS content from an external source.
There are a few high level steps to follow to integrate the File Picker into your application.
First, you'll need to prompt the user to authenticate against PowerDMS and grant your application access on their behalf. This is accomplised by implementing an Open Id Connect Code Flow. You'll need to save the refresh token so that you can request access tokens in the future so that the user does not need to continue to authenticate. See Authenticating via the File Picker for details.
Once you've received an access token, you'll then need to display the File Picker. You'll pass in the access token and other configuration parameters. See Displaying the PowerDMS File Picker for more details.
Access tokens are valid for 1 hour. Once expired, they can be refreshed using the refresh_token that's returned as part of the initial authentication call. The File Picker will automatically call a configurable endpoint to generate a new access token. The details of this contract are outlined in the section Renewing the access token.
The File Picker uses Open ID Connect Code Flow (OIDC Code Flow) for authentication. When the authentication function is called, we will open a new window that initiates the authentication flow. To implement authentication you'll:
Reference the following stylesheet and initialization script files on the consuming page:
<linkrel="stylesheet" href="https://filepicker.powerdms.com/initializer/powerDmsFilePicker.css" type="text/css"><scriptsrc="https://filepicker.powerdms.com/initializer/powerDmsFilePicker.js"></script>
Call the
window.PowerDms.openAuthModalfunction, passing in a config object. The structure of the config object is detailed in the Authentication Configuration section.functionopenAuthModal(clientConfig){// Creating a state object with the username encoded. You can // add whatever other information you want hereconststate={hash: // A HASH YOU GENERATE AND STOREusername: // YOUR USERNAME}varencodedState=encodeURIComponent(btoa(JSON.stringify(state)));varconfig={clientId: // YOUR CLIENT ID,redirectUrl: // YOUR REDIRECT URL,state: encodedState,};window.PowerDms.openAuthModal(config);}
This will open a separate browser window and start the login flow:
Implement the callback to retrieve the OIDC tokens. Upon successful authentication, the user will be redirected back to the
redirectUrlwith query string parameters reflecting the code and state in the formredirectUrl?code=${code}&state=${state}. You will need to make a POST request tohttps://accounts.powerdms.com/oauth/tokenwith the following form-url encoded parameters:- grant_type = authorization_code
- client_id = The client id supplied by PowerDMS
- client_secret = The client secret supplied by PowerDMS. This is sensitive and should never be shared or returned to the browser.
- code = The authorization code passed as a query string parameter after successful authentication.
- redirect_uri = Your redirect url. This must be in the list of allowed URIs for this client.
The following is a sample HTTP request:
POST https://accounts.powerdms.com/oauth/tokenContent-Type: application/x-www-form-urlencodedgrant_type=authorization_code&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&code=AUTHORIZATION_CODE&redirect_uri=https://YOUR_APP/callback
This is an example response:
HTTP/1.1 200 OKContent-Type: application/json { "access_token":"eyJz93a...k4laUWw", "refresh_token":"GEbRxBN...edjnXbL", "id_token":"eyJ0XAi...4faeEoQ", "token_type":"Bearer", "expires_in":86400 }
After retrieving the tokens, you'll need to save your refresh tokens for later retrieval, and then complete the auth flow by redirecting the user to the File Picker with the correct tokens. The full redirect url will be:
https://filepicker.powerdms.com/auth-finalize?$access_token=YOUR_ACCESS_TOKEN&client_id=YOUR_CLIENT_ID&id_token=YOUR_ID_TOKEN&locale=YOUR_LOCALE&redirect_url=https://YOUR_APP/callbackBelow is sample C# code implementing this step:
[HttpGet,Route("callback")]publicasyncTask<ActionResult>Callback(stringcode,stringstate,stringerror,stringerror_description){if(!string.IsNullOrEmpty(error)){returnnewJsonResult(new{error,error_description});}varurl=$"{AuthServerHost}/oauth/token";varcontent=newFormUrlEncodedContent(newDictionary<string,string>{["grant_type"]="authorization_code",["client_id"]=ClientID,["client_secret"]=ClientSecret,["code"]=code,["redirect_uri"]=$"http://localhost:8008/callback"});varhttpClient=newHttpClient();varresponse=awaithttpClient.PostAsync(url,content);if(response.IsSuccessStatusCode){varresponseJson=awaitresponse.Content.ReadAsStringAsync();vartokenResponse=JsonSerializer.Deserialize<TokenResponse>(responseJson);// save refresh tokenMemoryCache.Default["refreshToken"]=tokenResponse.refresh_token;varresponseUrl=$"{FilePickerHost}/auth-finalize?"+$"access_token={Uri.EscapeDataString(tokenResponse.access_token)}&"+$"client_id={Uri.EscapeDataString(ClientID)}&"+$"id_token={Uri.EscapeDataString(tokenResponse.id_token)}&"+$"redirect_url={Uri.EscapeDataString("http://localhost:8008/callback")}";returnnewRedirectResult(responseUrl);}returnnull;}publicclassTokenResponse{publicstringaccess_token{get;set;}publicstringrefresh_token{get;set;}publicstringid_token{get;set;}publicstringtoken_type{get;set;}}
At a high level, the PowerDMS File Picker is implemented as an iFrame that gets embedded into your application. Follow these three simple steps to get started.
Create a function that will be called when a user makes a selection:
functiondisplaySelection(response){varjson=JSON.stringify(response);varmessage='Selection: \n'+json;alert(message);}
The
responsewill include a list of selected documents that gets passed on to the consuming page, including the URLs that can be used to get the files from the PowerDMS API.Call the function
openFilePickerfrom the consuming page using a button:functionreceiveMessage(event){if(event.origin!=='https://filepicker.powerdms.com'){return;}varmessage=event.data;if(message.type==='DMS_FILEPICKER_SENDTOKENSTOHOST'){consttokens=message.data;constconfig={accessToken: tokens.accessToken,idToken: tokens.idToken,tokenRefreshUrl: window.location.origin+'/refresh',onSelection: displayResponse,};window.PowerDms.openFilePicker(config);}}window.addEventListener('message',receiveMessage,false);
This will open the file picker inside your web application:
The
configurationprovided toopenFilePickermust include theAPI Keyprovided by PowerDMS for your application and the function you previously created to receive theonSelectioncallback when the user selects documents.
Our access tokens expire after 1 hour. Expired access tokens will need to be renewed. The File Picker automatically renews access tokens that are no longer valid by calling the endpoint specified on the tokenRefreshUrl? configuration option. This is an endpoint that you must implement that conforms to a contract that the File Picker expects. The endpoint must be a POST that accepts the idToken and the partner's username. This endpoint should look up the refresh token that is tied to the user id and call the https://accounts.powerdms.com/oauth/token endpoint. The form of this call should be:
POST https://accounts.powerdms.com/oauth/tokenContent-Type: application/x-www-form-urlencodedgrant_type=refresh_token&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&refresh_token=YOUR_REFRESH_TOKENHere is an example endpoint in C# using Web API:
[HttpPost,Route("refresh")]publicasyncTask<ActionResult>Refresh([FromQuery(Name="id_token")]stringidToken,stringusername){// get last saved refresh tokenvarrefreshToken=MemoryCache.Default["refreshToken"].ToString();varurl=$"{AuthServerHost}/oauth/token";varcontent=newFormUrlEncodedContent(newDictionary<string,string>{["grant_type"]="refresh_token",["client_id"]=ClientID,["client_secret"]=ClientSecret,["refresh_token"]=refreshToken});varhttpClient=newHttpClient();varresponse=awaithttpClient.PostAsync(url,content);if(!response.IsSuccessStatusCode){thrownewException($"Failed to get tokens ({response.ReasonPhrase})");}varjson=awaitresponse.Content.ReadAsStringAsync();// see structure of token response belowvartokenResponse=JsonSerializer.Deserialize<TokenResponse>(json);returnnewOkObjectResult(new{AccessToken=tokenResponse.access_token,IdToken=tokenResponse.id_token});}The PowerDMS File Picker returns metadata corresponding to the files a user selected. Using the PowerDMS API, your application can extend this functionality and build custom integration experiences.
This section provides examples for some common scenarios.
The PowerDMS File Picker SelectedFileResponse object contains the information necessary to download the files corresponding to the the documents selected by the user.
Using the documentId and revisionId from a selected document, call the Get File by ID endpoint using an authorized request:
GET https://api.powerdms.com/v1/documents/{documentId}/revisions/{revisionId}/contentFor your convenience, the url used to download the file for the selected document is also included as the contentUrl property.
See the specific endpoint documentation for Getting Files in the PowerDMS API.
You can construct a link to the selected document that allows an authenticated user to view the latest version of the selected document within PowerDMS.com with the following format:
https://powerdms.com/link/{siteKey}/document/?id={documentId}{siteKey}is the unique identifier that corresponds to the organization in PowerDMS the user is logged into. This is not a part of the File Picker response and will need to be prompted for in a different way.{documentId}is the id of the selected document. This is provided by thedocumentIdproperty on the selected file object.
For example, to link to document 201893 in site AcmeCorp, you'll construct a link that looks like the following:
https://powerdms.com/link/AcmeCorp/document/?id=201893You can also link to a specific version of a selected document that was active on a certain date in PowerDMS.com. This will require you to request published revisions on a specific date using the API.
Call the Published Revisions for Documents in date endpoint using an authorized request and specify the date the revisions should have been published for a set of documents.
The following example would provide the revisions that were active on October 5th, 2019 for documents 15560, 28915, and 78137:
POST https://api.powerdms.com/v1/documents/past-published-revisions
{
"targetDate": "2019-10-05T04:00:00.000Z",
"documentIds": [15560, 28915, 78137]
}The timezone in targetDate is optional. The site's default timezone will be used if not included.
This endpoint will return the active revision at the targetDate for each documentId provided. The example response for the above call would be:
{
"data": [
{
"documentId": "15560",
"isPublicationFound": true,
"publishedRevision": {
"documentRevisionId": "39405",
"deepLinkUri": "https://powerdms.com/link/AcmeCorp/revision/?ID=39405"
}
},
{
"documentId": "28915",
"isPublicationFound": false,
"publishedRevision": null
},
{
"documentId": "78137",
"isPublicationFound": false,
"publishedRevision": null
} ],
"error": null
}If there was no published revision for the document on the specific date, the this will be false and the publishedRevision will be null.
Using the above response, the link to a specific revision would be provided in the deepLinkUri property:
https://powerdms.com/link/AcmeCorp/revision/?ID=39405See the specific endpoint documentation for Getting Revisions in the PowerDMS API.
PowerDms is a top level namespace that will house all PowerDMS File Picker API classes.
The window.PowerDms.openAuthModal function accepts a configuration object as a single parameter. This object has the following structure (in TypeScript):
typeAuthModalConfig={// Client Id supplied by PowerDMS clientId: string,// Url to your endpoint that will handle the code flow redirectUrl: string,// Optional width of the auth modalwidth?: number;// Optional height of the auth modalheight?: number;// The anti-csrf state parameter that will be passed back to redirectUrl after the user // successfully authenticates. We recommend encoding your user's id so that when retrieving // tokens, you can save tokens by user id. state?: string;}The initializePowerDmsFilePicker function accepts a configuration object as a single parameter. This object has the following structure (in TypeScript):
typeFilePickerConfig={// The access token from the OIDC Code Flow.accessToken?: string;// The desired height of the file picker, in pixels.// Restricted from 350 to 650.height?: number;// The id token from the OIDC Code Flow.idToken?: string// The local. Defaults to en-us.locale?: string;// A callback that is called when a user makes a selection.onSelection: (response: SelectionResponse)=>void;// This is the url that the File Picker will hit when the access token expires in order to // refresh the token. tokenRefreshUrl?: string;// The desired width of the file picker, in pixels.// Restricted from 566 to 1051.width?: number;}When files are selected, the onSelection callback is invoked with metadata about the selected files. The metadata has the following structure:
typeSelectionResponse={selectedFiles: ResponseFileInfo[];}typeResponseFileInfo={documentId: string;documentName: string;breadcrumbs: ResponseParentFolder[];revisionId: string;revisionStatus: ObjectStatus;// This will be the URL of an API endpoint to get the file contents.contentUrl: string;}enumObjectStatus{Draft='draft',Published='published',Archived='archived',}typeResponseParentFolder={id: number;name: string;}Here is an example of the response you'll get from selected 3 documents:
{
"selectedFiles":[
{
"documentId":"13211",
"documentName":"Conduct Policy (Public & Published)",
"breadcrumbs":[
{
"id":"13269",
"name":"Policies"
}
],
"revisionId":"38917",
"revisionStatus":"Publication",
"contentUrl":"http://powerdms.com/v1/documents/13211/revisions/38917/content"
},
{
"documentId":"13752",
"documentName":"Sexual Harassment Policy",
"breadcrumbs":[
{
"id":"13269",
"name":"Policies"
}
],
"revisionId":"35674",
"revisionStatus":"Publication",
"contentUrl":"http://powerdms.com/v1/documents/13752/revisions/35674/content"
},
{
"documentId":"17896",
"documentName":"Procedural Policy (Draft)",
"breadcrumbs":[
{
"id":"13269",
"name":"Policies"
}
],
"revisionId":"32154",
"revisionStatus":"Draft",
"contentUrl":"http://powerdms.com/v1/documents/17896/revisions/32154/content"
}
]
}

