Adds a listener to an event type.
When an event of the type pType fires, the callback pListener will be called. This function
returns a unique string id that may be used in removeEventListenerById to allow simple
listener removal.
It is possible to add an object that will be included in the callback to avoid creating too many closures.
Calling twice addEventListener with the same parameters results in the second call to be ignored,
only unique pairs callback / object are allowed, in order to avoid calling multiple times the same
thing.
The id of the inserted callback (actually an UUID).
Adds a listener to an event type.
When an event of the type pType fires, the callback pListener will be called. This function
returns a unique string id that may be used in removeEventListenerById to allow simple
listener removal.
The id of the inserted callback (actually an UUID).
Asynchronous - Sends a close request concerning the current authentication session on the directory.
This will also revoke all the DataSessionInterface that were created from this directory session. The DataSessionInterfaceSignal.DataSessionClosed signal may be sent after a while on the given DataSessionInterface, since DataSessionInterface objects are autonomous and will discover the closing of their session on their own.
If pForceAuthentication is set to true, SSO configuration will be flushed, forcing the user to reconnect on the next call to getPopupBasedAuthenticationUrl or getSamePageAuthenticationUrl. If pForceAuthentication is set to false, SSO configuration will be kept leading to, depending on your openid configuration, a silent and automatic connection on the next call to getPopupBasedAuthenticationUrl or getSamePageAuthenticationUrl.
If the user is not authenticated, this function does nothing and the waiting time is 0.
When the directory session is effectively closed, the promise is resolved.
A promise.
Asynchronously opens a DirectorySessionInterface in secondary session mode.
Once a DirectorySessionInterface has been fully loaded, a secondary DirectorySessionInterface may be open with asyncOpenSecondaryDirectorySession with the result of requestNewSecondaryDirectorySession called on the primary DirectorySessionInterface.
/**
* Sample to illustrate the asynchronous use of the primary/secondary session mechanism of DirectorySessionInterface
* and DataSessionInterface.
*/
import {
InfiniteCacheFactory, DirectorySessionFactory,
InfiniteCacheInterface, DirectorySessionInterface,
DataSessionInterface,
DataSessionInterfaceSignal, DirectorySessionInterfaceSignal,
SecondaryDirectorySessionInterfaceInfo,
SecondaryDataSessionInterfaceInfo,
AsyncDirectorySessionWaitForLoadedResult,
AsyncDirectorySessionWaitForLoadedResultReason,
AsyncDataSessionInterfaceOpenResult,
} from 'generated_files/documentation/appinfiniteapi';
// this sample holds the code to be use in the primary tab (primaryCode)
// and in the secondary tab (secondaryCode)
// a callback to receive messages
type tMessageHandler = (pMessage: any) => void;
// we suppose that there exists a message system
let sendMessage : (pMessage: any) => void;
// we suppose that we can register a handler to receive messages
let registerMessageHandler : (pMessageHandler: tMessageHandler) => void;
// the primary code
const primaryCode = () : void =>
{
// created previously
// this is the directory session that will server as primary session
// this DirectorySessionInterface should already be logged in
let lOriginalDirectorySession : DirectorySessionInterface;
// created previously
// this is the data session that will server as primary session
// this DataSessionInterface should already be connected
let lOriginalDataSession : DataSessionInterface;
// create a secondary session info to init the future secondary DirectorySessionInterface
const lSecondaryDirectorySessionInfo : SecondaryDirectorySessionInterfaceInfo | undefined = lOriginalDirectorySession.requestNewSecondaryDirectorySession();
if(lSecondaryDirectorySessionInfo === undefined)
{
// output some fancy error message
console.error('secondary directory session info creation failed');
return;
}
// create a secondary data session info to init the future secondary DataSessionInterface
// warning : this call will hold resources in the primary DataSessionInterface
// when the secondary data session is no longer useful
// release resources with unregisterSecondaryDataSession
// warning: there is a finite number of secondary data sessions that may be created
let lSecondaryDataSessionInfo : SecondaryDataSessionInterfaceInfo | undefined = lOriginalDataSession.requestNewSecondaryDataSession();
if(lSecondaryDataSessionInfo === undefined)
{
// output some fancy error message
console.error('secondary data session info creation failed');
return;
}
// called when the DirectorySessionInterface updates its tokens
const lDirectorySessionTokenUpdate = () : void => {
const lHttpBearer : string = lOriginalDirectorySession.getHttpBearer();
// only update tokens when the directory session is connected
if(lHttpBearer.length > 0)
{
// send the new directory session tokens to the secondary session
sendMessage({
type: 'directorySessionTokens',
httpBearer: lHttpBearer,
authenticationBearer: lOriginalDirectorySession.getAuthenticationBearer(),
extendedAuthenticationBearer: lOriginalDirectorySession.getExtendedAuthenticationBearer(),
});
}
};
// called when the DataSessionInterface updates its tokens
const lDataSessionTokenUpdate = () : void => {
const lDataSessionBearer : string = lOriginalDataSession.getDataSessionBearer();
// only update tokens when the data session is connected
if(lDataSessionBearer.length > 0)
{
// send the new data session tokens to the secondary session
sendMessage({
type: 'dataSessionTokens',
dataSessionBearer: lDataSessionBearer,
extendedDataSessionBearer: lOriginalDataSession.getExtendedDataSessionBearer(),
});
}
};
// message callback, receive messages from the secondary session
const onMessage : tMessageHandler = (pMessage : any) : void =>
{
switch(pMessage.type)
{
// cleanup the secondary data session resources
case 'dataSessionCleanup':
if(lSecondaryDataSessionInfo !== undefined)
{
lOriginalDataSession.unregisterSecondaryDataSession(lSecondaryDataSessionInfo);
// cleanup only once
lSecondaryDataSessionInfo = undefined;
}
break;
default:
// this should not happen, we have no other message types that we may receive
console.error('Unexpected message type');
break;
}
};
// and register the token update functions on token update
lOriginalDirectorySession.addEventListener(DirectorySessionInterfaceSignal.TokenUpdated, lDirectorySessionTokenUpdate);
lOriginalDataSession.addEventListener(DataSessionInterfaceSignal.TokenUpdated, lDataSessionTokenUpdate);
// register callbacks
registerMessageHandler(onMessage);
// we are ready, send the infos to load a new secondary directory and data session
sendMessage({
type: 'init',
directorySession: lSecondaryDirectorySessionInfo,
dataSession: lSecondaryDataSessionInfo,
// build id is required to create a data session on the correct build
buildId: lOriginalDataSession.getBuildId()
});
};
// the secondary session code
const secondaryCode = () : void =>
{
// create a directory session
const sDirectoryUrl : string = 'https://my_directory:443/directory';
// before connection, this is a "normal" one
const lSecondaryDirectorySession : DirectorySessionInterface = DirectorySessionFactory.CreateDirectorySession(sDirectoryUrl);
// Create a cache to avoid requesting heavy data from the server if data has been retrieved already
const lCache: InfiniteCacheInterface = InfiniteCacheFactory.CreateInfiniteCache();
// the new data session
// we cannot create it right now, we must wait for secondary session info and directory session login
let lSecondaryDataSession : DataSessionInterface;
// hold the open secondary info for future call
let lSecondaryDataSessionInterfaceInfo : SecondaryDataSessionInterfaceInfo;
// the build id we will be connected to
let lDataSessionBuildId : string = '';
// message callback, receive secondary sessions info and tokens
const onMessage : tMessageHandler = (pMessage : any) : void =>
{
switch(pMessage.type)
{
// secondary sessions infos
case 'init':
{
lSecondaryDataSessionInterfaceInfo = pMessage.dataSession;
lDataSessionBuildId = pMessage.buildId;
lSecondaryDirectorySession.asyncOpenSecondaryDirectorySession(pMessage.directorySession).then(
(pOpenResult: AsyncDirectorySessionWaitForLoadedResult) : void => {
if(pOpenResult.reason !== AsyncDirectorySessionWaitForLoadedResultReason.OpenResult_LoginSuccess)
{
// and output some message if the data session opening failed
console.error('directory session opening failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
return;
}
// weird, we should have a build id at this time
if(lDataSessionBuildId.length === 0)
{
// and output some message if the data session creation failed
console.error('data session creation failed, empty build id');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
return;
}
// actually create the DataSessionInterface
lSecondaryDataSession = lSecondaryDirectorySession.createDataSession(lDataSessionBuildId, lCache);
if(lSecondaryDataSession === undefined)
{
// and output some message if the data session creation failed
console.error('data session creation failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
return;
}
// open it in secondary session mode
lSecondaryDataSession.asyncOpenSecondaryDataSession(lSecondaryDataSessionInterfaceInfo).then(
(pDataSessionResult: AsyncDataSessionInterfaceOpenResult) : void =>
{
if(pDataSessionResult !== AsyncDataSessionInterfaceOpenResult.OpenResult_Success)
{
// and output some message if the data session opening failed
console.error('secondary data session opening failed');
// get rid of data
lSecondaryDataSession.dispose();
lSecondaryDataSession = undefined;
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
// and do some fancy things there :)
// we are connected correctly
}
);
}
);
break;
}
case 'directorySessionTokens':
{
// do nothing if the directory session is not connected
if(!lSecondaryDirectorySession.isAuthenticated())
{
return;
}
// and update the tokens
const lResult : boolean = lSecondaryDirectorySession.setTokenValues(pMessage.httpBearer, pMessage.authenticationBearer, pMessage.extendedAuthenticationBearer);
if(!lResult)
{
// and output some message if the token update failed
console.error('set token values failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
break;
}
case 'dataSessionTokens':
{
// do nothing if the data session is not connected nor created
if(lSecondaryDataSession === undefined || !lSecondaryDataSession.isConnected())
{
return;
}
// and update the tokens
const lResult : boolean = lSecondaryDataSession.setTokenValues(pMessage.dataSessionBearer, pMessage.extendedDataSessionBearer);
if(!lResult)
{
// and output some message if the token update failed
console.error('set token values failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
break;
}
default:
// this should not happen, we have no other message types that we may receive
console.error('Unexpected message type');
break;
}
};
// register callbacks
registerMessageHandler(onMessage);
};
// in the primary part
primaryCode();
// in the secondary part
secondaryCode();
A promise.
Asynchronous - Requests a refresh of the access rights on the current directory session (build list, projects, report info, tags, teams).
Access rights information is available after a successful login (from attachments of DirectorySessionInterfaceSignal.LoginSuccess) but they can be updated during the session life.
The AsyncDirectorySessionRefreshAccessRightsReason of the AsyncDirectorySessionWaitForRefreshAccessRightsResult may be :
A promise with the result of the access rights reason.
Waits for the popup authentication to complete.
The AsyncDirectorySessionWaitForLoadedResultReason of the AsyncDirectorySessionWaitForLoadedResult may be :
A promise.
Sends a close request concerning the current authentication session on the directory.
This will also revoke all the DataSessionInterface that were created from this directory session. The DataSessionInterfaceSignal.DataSessionClosed signal may be sent after a while on the given DataSessionInterface, since DataSessionInterface objects are autonomous and will discover the closing of their session on their own.
If pForceAuthentication is set to true, SSO configuration will be flushed, forcing the user to reconnect on the next call to getPopupBasedAuthenticationUrl or getSamePageAuthenticationUrl. If pForceAuthentication is set to false, SSO configuration will be kept leading to, depending on your openid configuration, a silent and automatic connection on the next call to getPopupBasedAuthenticationUrl or getSamePageAuthenticationUrl.
If the user is not authenticated, this function does nothing.
Creates a data session concerning the given build id, with the given cache.
The newly data session or undefined if the DirectorySessionInterface is not authenticated to the directory.
Gets rid of this object.
After this call, this object can no longer be used.
If the object is an InfiniteObjectDispatcherInterface, then the InfiniteObjectDispatcherInterfaceSignal.ObjectDisposed signal is emitted.
Further uses of the object (with the exception of isDisposed, getInfiniteObjectType and application id retrieval) will log a message with LogLevel.LL_UsingDisposedObject.
Gets the URL to the 3djuump Infinite directory API.
It is https://pDirectoryHost:pDirectoryPort/pDirectoryPath/ which was set by the factory DirectorySessionFactory.CreateDirectorySession.
The URL string of the directory API.
Gets the application data that was set with getPopupBasedAuthenticationUrl or getSamePageAuthenticationUrl.
The application data is set with DirectoryAuthenticationOption.applicationData.
The application data, or an empty string if no application data was set.
Gets the scopes that were granted by the infinite backend.
If the user has any access right thirdpartyscopes:any_value (attached to her, her team or the application) and any_value is requested through DirectoryAuthenticationOption.appClaims, then the user will be granted any_value has scope.
This feature is useful to then make some request to a third party server with the directory token.
true if the call succeeded, i.e. pScopes is an Array.
Gets the Infinite token of the current directory session authentication.
Any http request to the directory should have the header x-infinite-bearer : <DirectorySessionInterface.getAuthenticationBearer()>.
If the directory session is not connected, returns an empty string.
The Infinite token.
Gets the current token hash that may be used to reconnect the directory in case of a page refresh, skipping authentication.
Such a hash may be stored within the storage api of the browser and used with setTokenFromHash.
If the DirectorySessionInterface is not connected, an empty string is returned. If the given DirectorySessionInterface is closed and the hash is used on another DirectorySessionInterface, the setTokenFromHash procedure will fail and DirectorySessionInterfaceSignal.LoginFailed will be called.
The current token hash.
Gets the id of the application as registered in the 3djuump Infinite admin page.
This may be used to call specific api calls to the Infinite backend.
If the authentication has not been performed, returns an empty strings.
The directory application id.
Gets the extended Infinite token of the current directory session authentication (if open with extended rights, see DirectoryAuthenticationOption.requestExtendedBearer).
Any http request to the directory may have the header x-infinite-bearer : <DirectorySessionInterface.getExtendedAuthenticationBearer()>.
If the directory session is not connected or not open with extended rights, returns an empty string.
The Infinite token.
Gets the Bearer of the current http directory session authentication.
Any http request to the directory should have the header Authorization : Bearer <DirectorySessionInterface.getHttpBearer()>.
If the directory session is not connected, returns an empty string.
The Bearer of the http authentication.
Tells the type of the given interface.
The type of the given interface.
Opens a new authentication session on the directory with the pop up mechanism, asking the user to authenticate.
A new tab is not opened by this function, the user will have to call window.open(getPopupBasedAuthenticationUrl()). Depending on your openid connect configuration, this may be a silent procedure for the user. This function makes use of the localStorage of the browser internally.
This function may return a string if successful, AuthenticationGetURLResult.DoNotReAuthenticate if the DirectorySessionInterface is already connected, AuthenticationGetURLResult.InvalidSession if an internal error occurred (unlikely) and AuthenticationGetURLResult.EmptyCallbackURI if pRedirectURI is an empty string.
An extended token may be requested with the options, in this case, the access token will contain additional information (subid, teams, etc ...). An application data may also be passed along. Some application claims may also be passed along.
/**
* Sample to illustrate the popup based authentication mechanism.
*/
import {
InfiniteFactory, InfiniteCacheFactory, DirectorySessionFactory,
InfiniteEngineInterface, InfiniteCacheInterface, DirectorySessionInterface,
InfiniteEvent, ConnectionData,
DataSessionInterfaceSignal, DirectorySessionInterfaceSignal,
} from 'generated_files/documentation/appinfiniteapi';
// authentication url as defined in the directory
// authenticate.html must include your authentication script
const sAuthenticationUrl : string = 'https://your_server/your_application/authenticate.html';
const sDirectoryUrl : string = 'https://my_directory:443/directory';
// Create a 3D engine to handle the rendering of the DMU. The engine is optional if you
// just want to search data in the DMU, but required to display 3D data.
// you need to provide a div inside your html file, or create one div programmatically
const lInfiniteEngine: InfiniteEngineInterface = InfiniteFactory.CreateInfiniteEngine();
// bind the engine to the given div that will be used for rendering
lInfiniteEngine.setView(document.getElementById('rendering'));
// Create a cache to avoid requesting heavy data from the server if data has been retrieved already
const lCache: InfiniteCacheInterface = InfiniteCacheFactory.CreateInfiniteCache();
// what to do to authenticate (authenticate function may be bound to a div `click` or called straight away)
let authenticate : () => void = undefined;
// Success callback on login
let onLoginSuccess : (pEvent: InfiniteEvent, _pCallbackData: Object | undefined) => void = undefined;
// Success callback when DataSession is ready
let onDMULoaded : (_pEvent: InfiniteEvent, _pCallbackData: Object | undefined) => void = undefined;
// *****************************************************************************
// ******************************* Authentication ******************************
// *****************************************************************************
// what to do to authenticate (authenticate function may be bound to a div `click` or called straight away)
authenticate = () : void =>
{
// connect to directory with address sDirectoryAddress, in the folder "/directory" through https. The default port is unchanged (443)
const lDirectorySession: DirectorySessionInterface = DirectorySessionFactory.CreateDirectorySession(sDirectoryUrl);
// do something when we are connected !!!! => onLoginSuccess
lDirectorySession.addEventListener(DirectorySessionInterfaceSignal.LoginSuccess, onLoginSuccess);
// retrieve the url to contact to begin authentication with popup
// that also starts the authentication procedure
const sURL = lDirectorySession.getPopupBasedAuthenticationUrl(sAuthenticationUrl);
if (typeof sURL === 'string') {
if (sURL !== '' && sURL.includes('authenticate'))
{
// popup based authentication
window.open(sURL);
}
}
};
// Success callback on login
onLoginSuccess = (pEvent: InfiniteEvent, _pCallbackData: Object | undefined) : void =>
{
// Get the Connection Data to get the build lists
const lConnectionData: ConnectionData = <ConnectionData>pEvent.attachments;
// Get the list of projects => do something as you like
const lProjectList = lConnectionData.projects;
for (const lProjectId in lProjectList)
{
// iterate but get the first project
const lBuildList = lProjectList[lProjectId].builds;
for (const lBuild in lBuildList)
{
// iterate but get the first build
// create a data session that uses the cache with the first item
const lDataSession = (<DirectorySessionInterface>(pEvent.emitter)).createDataSession(lBuild, lCache);
if (lDataSession)
{
// bind the given data session to the Infinite engine
lDataSession.bindInfiniteEngine(lInfiniteEngine);
// be ready to do something when build is ready (i.e. all init data has been parsed and server is ready)
lDataSession.addEventListener(DataSessionInterfaceSignal.DMULoadingSuccess, onDMULoaded);
// and go !!! => open the data session
lDataSession.openDataSession();
}
return;
}
}
};
// Success callback when DataSession is ready
onDMULoaded = (_pEvent: InfiniteEvent, _pCallbackData: Object | undefined) : void =>
{
// do something !!!
// create filters
// change visibility
// etc ....
};
authenticate();
Optional pOpenOptions: DirectoryAuthenticationOptionThe authentication URL to visit to start the authentication procedure if successful, AuthenticationGetURLResult.DoNotReAuthenticate if the DirectorySessionInterface is already connected, AuthenticationGetURLResult.InvalidSession if an internal error occurred and AuthenticationGetURLResult.EmptyCallbackURI if pRedirectURI is an empty string.
Opens a new authentication session on the directory with the same page mechanism, asking the user to authenticate.
Depending on your openid connect configuration, this may be a silent procedure for the user.
This function may return a string if successful, AuthenticationGetURLResult.DoNotReAuthenticate if the DirectorySessionInterface is already connected, AuthenticationGetURLResult.InvalidSession if an internal error occurred (unlikely) and AuthenticationGetURLResult.EmptyCallbackURI if pRedirectURI is an empty string.
An extended token may be requested with the options, in this case, the access token will contain additional information (subid, teams, etc ...). An application data may also be passed along. Some application claims may also be passed along.
/**
* Sample to illustrate the same page authentication mechanism.
*/
import {
InfiniteFactory, InfiniteCacheFactory, DirectorySessionFactory,
InfiniteEngineInterface, InfiniteCacheInterface, DirectorySessionInterface,
InfiniteEvent, ConnectionData,
DataSessionInterfaceSignal, DirectorySessionInterfaceSignal,
} from 'generated_files/documentation/appinfiniteapi';
// the current page (without url parameters) should be registered as authentication url in the directory
const sDirectoryUrl : string = 'https://my_directory:443/directory';
let lInfiniteEngine: InfiniteEngineInterface | undefined = undefined;
let lCache: InfiniteCacheInterface | undefined = undefined;
let lDirectorySession: DirectorySessionInterface | undefined = undefined;
// what to do to authenticate (authenticate function may be bound to a div `click` or called straight away)
let authenticate : () => void = undefined;
// Checks if the url has an hash in order to authenticate
let checkHash : () => void = undefined;
// Success callback on login
let onLoginSuccess : (pEvent: InfiniteEvent, _pCallbackData: Object | undefined) => void;
// Success callback when DataSession is ready
let onDMULoaded : (_pEvent: InfiniteEvent, _pCallbackData: Object | undefined) => void;
// *****************************************************************************
// ******************************* Authentication ******************************
// *****************************************************************************
// what to do to authenticate (authenticate function may be bound to a div `click` or called straight away)
authenticate = () : void =>
{
// if we have a hash, do not request a new authentication
if (window.location.hash.length > 0)
{
// perhaps some GUI code there
return;
}
// connect to directory with address sDirectoryAddress, in the folder "/directory" through https. The default port is unchanged (443)
lDirectorySession = DirectorySessionFactory.CreateDirectorySession(sDirectoryUrl);
// redirect url is the current url without query parameters
// the directory needs a full url (with query parameters if needed), so we recommend to
// register the url without parameters, use this url as authentication, store the url parameters if present
// and then redirect to the "final url" (see checkHash)
const sRedirectUrl : string = window.location.origin + window.location.pathname;
if (window.location.href.includes('?'))
{
// store the url with query parameters in session storage
// we will finally redirect to this url
window.sessionStorage.setItem('redirecturl', window.location.href.split('#')[0]);
}
const sURL = lDirectorySession.getSamePageAuthenticationUrl(sRedirectUrl);
if (typeof sURL === 'string')
{
// navigate to the given url for authentication
window.location.href = sURL;
}
else
{
console.log('Error not expected !!! ' + sURL);
window.sessionStorage.removeItem('redirecturl');
}
};
// Checks if the url has an hash in order to authenticate
checkHash = () : void =>
{
const lHash : string = window.location.hash;
if (lHash.length === 0)
{
// do not bother if no hash
return;
}
// we may here put some GUI code
// here we can check if the url has query parameters
const lSessionItem : string | null = window.sessionStorage.getItem('redirecturl');
if (lSessionItem)
{
// we have a redirect url
// remove it from storage in order to avoid infinite redirects
window.sessionStorage.removeItem('redirecturl');
// navigate to this url with hash
window.location.replace(lSessionItem + lHash);
}
else
{
// remove hash with some fancy methods
if (window.history.replaceState)
{
const uri : string = window.location.toString();
const cleanUri : string = uri.substring(0, uri.indexOf('#'));
window.history.replaceState({}, document.title, cleanUri);
}
else
{
window.location.hash = '';
}
lDirectorySession = DirectorySessionFactory.CreateDirectorySession(sDirectoryUrl);
// do something when we are connected !!!! => onLoginSuccess
lDirectorySession.addEventListener(DirectorySessionInterfaceSignal.LoginSuccess, onLoginSuccess);
// and end authentication
lDirectorySession.setTokenFromHash(lHash);
}
};
// Success callback on login
onLoginSuccess = (pEvent: InfiniteEvent, _pCallbackData: Object | undefined) : void =>
{
// Create a 3D engine to handle the rendering of the DMU. The engine is optional if you
// just want to search data in the DMU, but required to display 3D data.
// you need to provide a div inside your html file, or create one div programmatically
lInfiniteEngine = InfiniteFactory.CreateInfiniteEngine();
// bind the engine to the given div that will be used for rendering
lInfiniteEngine.setView(document.getElementById('rendering'));
// Create a cache to avoid requesting heavy data from the server if data has been retrieved already
lCache = InfiniteCacheFactory.CreateInfiniteCache();
// Get the Connection Data to get the build lists
const lConnectionData: ConnectionData = <ConnectionData>pEvent.attachments;
// Get the list of projects => do something as you like
const lProjectList = lConnectionData.projects;
for (const lProjectId in lProjectList)
{
// iterate but get the first project
const lBuildList = lProjectList[lProjectId].builds;
for (const lBuild in lBuildList)
{
// iterate but get the first build
// create a data session that uses the cache with the first item
const lDataSession = (<DirectorySessionInterface>(pEvent.emitter)).createDataSession(lBuild, lCache);
if (lDataSession)
{
lDataSession.bindInfiniteEngine(lInfiniteEngine);
// be ready to do something when build is ready (i.e. all init data has been parsed and server is ready)
lDataSession.addEventListener(DataSessionInterfaceSignal.DMULoadingSuccess, onDMULoaded);
// and go !!! => open the data session
lDataSession.openDataSession();
}
return;
}
}
};
// Success callback when DataSession is ready
onDMULoaded = (_pEvent: InfiniteEvent, _pCallbackData: Object | undefined) : void =>
{
// do something !!!
// create filters
// change visibility
// etc ....
};
// we may launch an authentication procedure (or from a button)
authenticate();
// check hash if we should validate the authentication
checkHash();
Optional pOpenOptions: DirectoryAuthenticationOptionThe authentication URL to visit to start the authentication procedure if successful, AuthenticationGetURLResult.DoNotReAuthenticate if the DirectorySessionInterface is already connected, AuthenticationGetURLResult.InvalidSession if an internal error occurred and AuthenticationGetURLResult.EmptyCallbackURI if pRedirectURI is an empty string.
Gets a copy of the user information (name, initials and picture URL).
If the authentication has not been performed, all fields are set to empty strings.
The UserData containing the name (string) the initials (string) and the picture url (string) of the logged-in user.
Tells if the EventDispatcher has such a callback registered for the given event type.
true if such a listener is installed for the given type of event.
Tells if this object has been gotten rid off.
true if dispose has been called on this object.
Tells if the DirectorySessionInterface is configured as "primary" session behavior.
The DirectorySessionInterface is by default configured as "primary" session.
Once open in secondary session mode with openSecondaryDirectorySession, the DirectorySessionInterface will remain all the time in secondary session mode.
The primary session behavior consists in updating the bearers (getAuthenticationBearer, getExtendedAuthenticationBearer and getHttpBearer) regularly while a secondary DirectorySessionInterface should receive the new bearers with setTokenValues. This primary/secondary session mechanism allows to use multiple directory sessions objects that share the same directory session on the server. This may be useful to share the same directory session upon multiple tabs of the browser.
true if the DirectorySessionInterface is configured as primary session behavior.
Opens a DirectorySessionInterface in secondary session mode.
Once a DirectorySessionInterface has been fully loaded, a secondary DirectorySessionInterface may be open with openSecondaryDirectorySession with the result of requestNewSecondaryDirectorySession called on the primary DirectorySessionInterface.
/**
* Sample to illustrate the use of the primary/secondary session mechanism of DirectorySessionInterface and DataSessionInterface.
*/
import {
InfiniteCacheFactory, DirectorySessionFactory,
InfiniteCacheInterface, DirectorySessionInterface,
DataSessionInterface,
DataSessionInterfaceSignal, DirectorySessionInterfaceSignal,
SecondaryDirectorySessionInterfaceInfo,
SecondaryDataSessionInterfaceInfo,
AuthenticationGetURLResult,
} from 'generated_files/documentation/appinfiniteapi';
// this sample holds the code to be use in the primary tab (primaryCode)
// and in the secondary tab (secondaryCode)
// a callback to receive messages
type tMessageHandler = (pMessage: any) => void;
// we suppose that there exists a message system
let sendMessage : (pMessage: any) => void;
// we suppose that we can register a handler to receive messages
let registerMessageHandler : (pMessageHandler: tMessageHandler) => void;
// the primary code
const primaryCode = () : void =>
{
// created previously
// this is the directory session that will server as primary session
// this DirectorySessionInterface should already be logged in
let lOriginalDirectorySession : DirectorySessionInterface;
// created previously
// this is the data session that will server as primary session
// this DataSessionInterface should already be primary session
let lOriginalDataSession : DataSessionInterface;
// create a secondary session info to init the future secondary DirectorySessionInterface
const lSecondaryDirectorySessionInfo : SecondaryDirectorySessionInterfaceInfo | undefined = lOriginalDirectorySession.requestNewSecondaryDirectorySession();
if(lSecondaryDirectorySessionInfo === undefined)
{
// output some fancy error message
console.error('secondary directory session info creation failed');
return;
}
// create a secondary session info to init the future secondary DataSessionInterface
// warning : this call will hold resources in the primary DataSessionInterface
// when the secondary data session is no longer useful
// release resources with unregisterSecondaryDataSession
// warning: there is a finite number of secondary data sessions that may be created
let lSecondaryDataSessionInfo : SecondaryDataSessionInterfaceInfo | undefined = lOriginalDataSession.requestNewSecondaryDataSession();
if(lSecondaryDataSessionInfo === undefined)
{
// output some fancy error message
console.error('secondary data session info creation failed');
return;
}
// called when the DirectorySessionInterface updates its tokens
const lDirectorySessionTokenUpdate = () : void => {
const lHttpBearer : string = lOriginalDirectorySession.getHttpBearer();
// only update tokens when the directory session is connected
if(lHttpBearer.length > 0)
{
// send the new directory session tokens to the secondary
sendMessage({
type: 'directorySessionTokens',
httpBearer: lHttpBearer,
authenticationBearer: lOriginalDirectorySession.getAuthenticationBearer(),
extendedAuthenticationBearer: lOriginalDirectorySession.getExtendedAuthenticationBearer(),
});
}
};
// called when the DataSessionInterface updates its tokens
const lDataSessionTokenUpdate = () : void => {
const lDataSessionBearer : string = lOriginalDataSession.getDataSessionBearer();
// only update tokens when the data session is connected
if(lDataSessionBearer.length > 0)
{
// send the new data session tokens to the secondary session
sendMessage({
type: 'dataSessionTokens',
dataSessionBearer: lDataSessionBearer,
extendedDataSessionBearer: lOriginalDataSession.getExtendedDataSessionBearer(),
});
}
};
// message callback, receive messages from the secondary session
const onMessage : tMessageHandler = (pMessage : any) : void =>
{
switch(pMessage.type)
{
// cleanup the secondary session resources
case 'dataSessionCleanup':
if(lSecondaryDataSessionInfo !== undefined)
{
lOriginalDataSession.unregisterSecondaryDataSession(lSecondaryDataSessionInfo);
// cleanup only once
lSecondaryDataSessionInfo = undefined;
}
break;
default:
// this should not happen, we have no other message types that we may receive
console.error('Unexpected message type');
break;
}
};
// and register the token update functions on token update
lOriginalDirectorySession.addEventListener(DirectorySessionInterfaceSignal.TokenUpdated, lDirectorySessionTokenUpdate);
lOriginalDataSession.addEventListener(DataSessionInterfaceSignal.TokenUpdated, lDataSessionTokenUpdate);
// register callbacks
registerMessageHandler(onMessage);
// we are ready, send the infos to load a new secondary directory and data session
sendMessage({
type: 'init',
directorySession: lSecondaryDirectorySessionInfo,
dataSession: lSecondaryDataSessionInfo,
// build id is required to create a data session on the correct build
buildId: lOriginalDataSession.getBuildId()
});
};
// the secondary session code
const secondaryCode = () : void =>
{
// create a directory session
const sDirectoryUrl : string = 'https://my_directory:443/directory';
// before connection, this is a "normal" one
const lSecondaryDirectorySession : DirectorySessionInterface = DirectorySessionFactory.CreateDirectorySession(sDirectoryUrl);
// Create a cache to avoid requesting heavy data from the server if data has been retrieved already
const lCache: InfiniteCacheInterface = InfiniteCacheFactory.CreateInfiniteCache();
// the new data session
// we cannot create it right now, we must wait for secondary session info and directory session login
let lSecondaryDataSession : DataSessionInterface;
// hold the open secondary session info for future call
let lSecondaryDataSessionInterfaceInfo : SecondaryDataSessionInterfaceInfo;
// the build id we will be connected to
let lDataSessionBuildId : string = '';
// Success callback on DirectorySessionInterface login
const onLoginSuccess = () : void => {
// weird, we should have a build id at this time
if(lDataSessionBuildId.length === 0)
{
// and output some message if the data session creation failed
console.error('data session creation failed, empty build id');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
return;
}
// actually create the DataSessionInterface
lSecondaryDataSession = lSecondaryDirectorySession.createDataSession(lDataSessionBuildId, lCache);
if(lSecondaryDataSession === undefined)
{
// and output some message if the data session creation failed
console.error('data session creation failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
return;
}
// open it in secondary session mode
if(!lSecondaryDataSession.openSecondaryDataSession(lSecondaryDataSessionInterfaceInfo))
{
// and output some message if the data session opening failed
console.error('secondary data session opening failed');
// get rid of data
lSecondaryDataSession.dispose();
lSecondaryDataSession = undefined;
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
// and then we must wait for the DataSessionInterface to be connected
};
// message callback, receive secondary sessions info and tokens
const onMessage : tMessageHandler = (pMessage : any) : void =>
{
switch(pMessage.type)
{
// secondary sessions infos
case 'init':
{
lSecondaryDataSessionInterfaceInfo = pMessage.dataSession;
lDataSessionBuildId = pMessage.buildId;
const lResult : AuthenticationGetURLResult = lSecondaryDirectorySession.openSecondaryDirectorySession(pMessage.directorySession);
if(lResult !== AuthenticationGetURLResult.AuthenticationPending)
{
// and output some message if the data session opening failed
console.error('directory session opening failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
break;
}
case 'directorySessionTokens':
{
// do nothing if the directory session is not connected
if(!lSecondaryDirectorySession.isAuthenticated())
{
return;
}
// and update the tokens
const lResult : boolean = lSecondaryDirectorySession.setTokenValues(pMessage.httpBearer, pMessage.authenticationBearer, pMessage.extendedAuthenticationBearer);
if(!lResult)
{
// and output some message if the token update failed
console.error('set token values failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
break;
}
case 'dataSessionTokens':
{
// do nothing if the data session is not connected nor created
if(lSecondaryDataSession === undefined || !lSecondaryDataSession.isConnected())
{
return;
}
// and update the tokens
const lResult : boolean = lSecondaryDataSession.setTokenValues(pMessage.dataSessionBearer, pMessage.extendedDataSessionBearer);
if(!lResult)
{
// and output some message if the token update failed
console.error('set token values failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
break;
}
default:
// this should not happen, we have no other message types that we may receive
console.error('Unexpected message type');
break;
}
};
// register callbacks
lSecondaryDirectorySession.addEventListener(DirectorySessionInterfaceSignal.LoginSuccess, onLoginSuccess);
registerMessageHandler(onMessage);
};
// in the primary part
primaryCode();
// in the secondary part
secondaryCode();
The result of the opening request.
Requests an asynchronous refresh of the access rights on the current directory session (build list, projects, report info, tags, teams).
Access rights information is available after a successful login (from attachments of DirectorySessionInterfaceSignal.LoginSuccess) but they can be updated during the session life.
The asynchronous request will trigger the signals DirectorySessionInterfaceSignal.AccessRightsRefreshed or DirectorySessionInterfaceSignal.AccessRightsRefreshFailed according to the request resolution.
false if the user is not logged-in.
Removes a listener from an event type.
If no such listener is found, then the function returns false and does nothing. You must use the exact parameters that were used in addEventListener to actually remove the listener.
The listener function that gets removed.
The listener object that was used when addEventListener was called.
true if the callback was removed else false.
Removes a listener from an event type.
If no such listener is found, then the function returns false and does nothing. You must use the exact parameters that were used in addEventListener to actually remove the listener.
The listener function that gets removed.
true if the callback was removed else false.
Removes a listener by its id.
If no such listener is found, then the function returns false and does nothing. You must use the return value of addEventListener to actually remove the listener.
true if the callback was removed else false.
Creates a SecondaryDirectorySessionInterfaceInfo in order to create a new secondary DirectorySessionInterface.
This opaque object may be streamed to another tab (for example) and then used with openSecondaryDirectorySession.
/**
* Sample to illustrate the use of the primary/secondary session mechanism of DirectorySessionInterface and DataSessionInterface.
*/
import {
InfiniteCacheFactory, DirectorySessionFactory,
InfiniteCacheInterface, DirectorySessionInterface,
DataSessionInterface,
DataSessionInterfaceSignal, DirectorySessionInterfaceSignal,
SecondaryDirectorySessionInterfaceInfo,
SecondaryDataSessionInterfaceInfo,
AuthenticationGetURLResult,
} from 'generated_files/documentation/appinfiniteapi';
// this sample holds the code to be use in the primary tab (primaryCode)
// and in the secondary tab (secondaryCode)
// a callback to receive messages
type tMessageHandler = (pMessage: any) => void;
// we suppose that there exists a message system
let sendMessage : (pMessage: any) => void;
// we suppose that we can register a handler to receive messages
let registerMessageHandler : (pMessageHandler: tMessageHandler) => void;
// the primary code
const primaryCode = () : void =>
{
// created previously
// this is the directory session that will server as primary session
// this DirectorySessionInterface should already be logged in
let lOriginalDirectorySession : DirectorySessionInterface;
// created previously
// this is the data session that will server as primary session
// this DataSessionInterface should already be primary session
let lOriginalDataSession : DataSessionInterface;
// create a secondary session info to init the future secondary DirectorySessionInterface
const lSecondaryDirectorySessionInfo : SecondaryDirectorySessionInterfaceInfo | undefined = lOriginalDirectorySession.requestNewSecondaryDirectorySession();
if(lSecondaryDirectorySessionInfo === undefined)
{
// output some fancy error message
console.error('secondary directory session info creation failed');
return;
}
// create a secondary session info to init the future secondary DataSessionInterface
// warning : this call will hold resources in the primary DataSessionInterface
// when the secondary data session is no longer useful
// release resources with unregisterSecondaryDataSession
// warning: there is a finite number of secondary data sessions that may be created
let lSecondaryDataSessionInfo : SecondaryDataSessionInterfaceInfo | undefined = lOriginalDataSession.requestNewSecondaryDataSession();
if(lSecondaryDataSessionInfo === undefined)
{
// output some fancy error message
console.error('secondary data session info creation failed');
return;
}
// called when the DirectorySessionInterface updates its tokens
const lDirectorySessionTokenUpdate = () : void => {
const lHttpBearer : string = lOriginalDirectorySession.getHttpBearer();
// only update tokens when the directory session is connected
if(lHttpBearer.length > 0)
{
// send the new directory session tokens to the secondary
sendMessage({
type: 'directorySessionTokens',
httpBearer: lHttpBearer,
authenticationBearer: lOriginalDirectorySession.getAuthenticationBearer(),
extendedAuthenticationBearer: lOriginalDirectorySession.getExtendedAuthenticationBearer(),
});
}
};
// called when the DataSessionInterface updates its tokens
const lDataSessionTokenUpdate = () : void => {
const lDataSessionBearer : string = lOriginalDataSession.getDataSessionBearer();
// only update tokens when the data session is connected
if(lDataSessionBearer.length > 0)
{
// send the new data session tokens to the secondary session
sendMessage({
type: 'dataSessionTokens',
dataSessionBearer: lDataSessionBearer,
extendedDataSessionBearer: lOriginalDataSession.getExtendedDataSessionBearer(),
});
}
};
// message callback, receive messages from the secondary session
const onMessage : tMessageHandler = (pMessage : any) : void =>
{
switch(pMessage.type)
{
// cleanup the secondary session resources
case 'dataSessionCleanup':
if(lSecondaryDataSessionInfo !== undefined)
{
lOriginalDataSession.unregisterSecondaryDataSession(lSecondaryDataSessionInfo);
// cleanup only once
lSecondaryDataSessionInfo = undefined;
}
break;
default:
// this should not happen, we have no other message types that we may receive
console.error('Unexpected message type');
break;
}
};
// and register the token update functions on token update
lOriginalDirectorySession.addEventListener(DirectorySessionInterfaceSignal.TokenUpdated, lDirectorySessionTokenUpdate);
lOriginalDataSession.addEventListener(DataSessionInterfaceSignal.TokenUpdated, lDataSessionTokenUpdate);
// register callbacks
registerMessageHandler(onMessage);
// we are ready, send the infos to load a new secondary directory and data session
sendMessage({
type: 'init',
directorySession: lSecondaryDirectorySessionInfo,
dataSession: lSecondaryDataSessionInfo,
// build id is required to create a data session on the correct build
buildId: lOriginalDataSession.getBuildId()
});
};
// the secondary session code
const secondaryCode = () : void =>
{
// create a directory session
const sDirectoryUrl : string = 'https://my_directory:443/directory';
// before connection, this is a "normal" one
const lSecondaryDirectorySession : DirectorySessionInterface = DirectorySessionFactory.CreateDirectorySession(sDirectoryUrl);
// Create a cache to avoid requesting heavy data from the server if data has been retrieved already
const lCache: InfiniteCacheInterface = InfiniteCacheFactory.CreateInfiniteCache();
// the new data session
// we cannot create it right now, we must wait for secondary session info and directory session login
let lSecondaryDataSession : DataSessionInterface;
// hold the open secondary session info for future call
let lSecondaryDataSessionInterfaceInfo : SecondaryDataSessionInterfaceInfo;
// the build id we will be connected to
let lDataSessionBuildId : string = '';
// Success callback on DirectorySessionInterface login
const onLoginSuccess = () : void => {
// weird, we should have a build id at this time
if(lDataSessionBuildId.length === 0)
{
// and output some message if the data session creation failed
console.error('data session creation failed, empty build id');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
return;
}
// actually create the DataSessionInterface
lSecondaryDataSession = lSecondaryDirectorySession.createDataSession(lDataSessionBuildId, lCache);
if(lSecondaryDataSession === undefined)
{
// and output some message if the data session creation failed
console.error('data session creation failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
return;
}
// open it in secondary session mode
if(!lSecondaryDataSession.openSecondaryDataSession(lSecondaryDataSessionInterfaceInfo))
{
// and output some message if the data session opening failed
console.error('secondary data session opening failed');
// get rid of data
lSecondaryDataSession.dispose();
lSecondaryDataSession = undefined;
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
// and then we must wait for the DataSessionInterface to be connected
};
// message callback, receive secondary sessions info and tokens
const onMessage : tMessageHandler = (pMessage : any) : void =>
{
switch(pMessage.type)
{
// secondary sessions infos
case 'init':
{
lSecondaryDataSessionInterfaceInfo = pMessage.dataSession;
lDataSessionBuildId = pMessage.buildId;
const lResult : AuthenticationGetURLResult = lSecondaryDirectorySession.openSecondaryDirectorySession(pMessage.directorySession);
if(lResult !== AuthenticationGetURLResult.AuthenticationPending)
{
// and output some message if the data session opening failed
console.error('directory session opening failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
break;
}
case 'directorySessionTokens':
{
// do nothing if the directory session is not connected
if(!lSecondaryDirectorySession.isAuthenticated())
{
return;
}
// and update the tokens
const lResult : boolean = lSecondaryDirectorySession.setTokenValues(pMessage.httpBearer, pMessage.authenticationBearer, pMessage.extendedAuthenticationBearer);
if(!lResult)
{
// and output some message if the token update failed
console.error('set token values failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
break;
}
case 'dataSessionTokens':
{
// do nothing if the data session is not connected nor created
if(lSecondaryDataSession === undefined || !lSecondaryDataSession.isConnected())
{
return;
}
// and update the tokens
const lResult : boolean = lSecondaryDataSession.setTokenValues(pMessage.dataSessionBearer, pMessage.extendedDataSessionBearer);
if(!lResult)
{
// and output some message if the token update failed
console.error('set token values failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
break;
}
default:
// this should not happen, we have no other message types that we may receive
console.error('Unexpected message type');
break;
}
};
// register callbacks
lSecondaryDirectorySession.addEventListener(DirectorySessionInterfaceSignal.LoginSuccess, onLoginSuccess);
registerMessageHandler(onMessage);
};
// in the primary part
primaryCode();
// in the secondary part
secondaryCode();
/**
* Sample to illustrate the asynchronous use of the primary/secondary session mechanism of DirectorySessionInterface
* and DataSessionInterface.
*/
import {
InfiniteCacheFactory, DirectorySessionFactory,
InfiniteCacheInterface, DirectorySessionInterface,
DataSessionInterface,
DataSessionInterfaceSignal, DirectorySessionInterfaceSignal,
SecondaryDirectorySessionInterfaceInfo,
SecondaryDataSessionInterfaceInfo,
AsyncDirectorySessionWaitForLoadedResult,
AsyncDirectorySessionWaitForLoadedResultReason,
AsyncDataSessionInterfaceOpenResult,
} from 'generated_files/documentation/appinfiniteapi';
// this sample holds the code to be use in the primary tab (primaryCode)
// and in the secondary tab (secondaryCode)
// a callback to receive messages
type tMessageHandler = (pMessage: any) => void;
// we suppose that there exists a message system
let sendMessage : (pMessage: any) => void;
// we suppose that we can register a handler to receive messages
let registerMessageHandler : (pMessageHandler: tMessageHandler) => void;
// the primary code
const primaryCode = () : void =>
{
// created previously
// this is the directory session that will server as primary session
// this DirectorySessionInterface should already be logged in
let lOriginalDirectorySession : DirectorySessionInterface;
// created previously
// this is the data session that will server as primary session
// this DataSessionInterface should already be connected
let lOriginalDataSession : DataSessionInterface;
// create a secondary session info to init the future secondary DirectorySessionInterface
const lSecondaryDirectorySessionInfo : SecondaryDirectorySessionInterfaceInfo | undefined = lOriginalDirectorySession.requestNewSecondaryDirectorySession();
if(lSecondaryDirectorySessionInfo === undefined)
{
// output some fancy error message
console.error('secondary directory session info creation failed');
return;
}
// create a secondary data session info to init the future secondary DataSessionInterface
// warning : this call will hold resources in the primary DataSessionInterface
// when the secondary data session is no longer useful
// release resources with unregisterSecondaryDataSession
// warning: there is a finite number of secondary data sessions that may be created
let lSecondaryDataSessionInfo : SecondaryDataSessionInterfaceInfo | undefined = lOriginalDataSession.requestNewSecondaryDataSession();
if(lSecondaryDataSessionInfo === undefined)
{
// output some fancy error message
console.error('secondary data session info creation failed');
return;
}
// called when the DirectorySessionInterface updates its tokens
const lDirectorySessionTokenUpdate = () : void => {
const lHttpBearer : string = lOriginalDirectorySession.getHttpBearer();
// only update tokens when the directory session is connected
if(lHttpBearer.length > 0)
{
// send the new directory session tokens to the secondary session
sendMessage({
type: 'directorySessionTokens',
httpBearer: lHttpBearer,
authenticationBearer: lOriginalDirectorySession.getAuthenticationBearer(),
extendedAuthenticationBearer: lOriginalDirectorySession.getExtendedAuthenticationBearer(),
});
}
};
// called when the DataSessionInterface updates its tokens
const lDataSessionTokenUpdate = () : void => {
const lDataSessionBearer : string = lOriginalDataSession.getDataSessionBearer();
// only update tokens when the data session is connected
if(lDataSessionBearer.length > 0)
{
// send the new data session tokens to the secondary session
sendMessage({
type: 'dataSessionTokens',
dataSessionBearer: lDataSessionBearer,
extendedDataSessionBearer: lOriginalDataSession.getExtendedDataSessionBearer(),
});
}
};
// message callback, receive messages from the secondary session
const onMessage : tMessageHandler = (pMessage : any) : void =>
{
switch(pMessage.type)
{
// cleanup the secondary data session resources
case 'dataSessionCleanup':
if(lSecondaryDataSessionInfo !== undefined)
{
lOriginalDataSession.unregisterSecondaryDataSession(lSecondaryDataSessionInfo);
// cleanup only once
lSecondaryDataSessionInfo = undefined;
}
break;
default:
// this should not happen, we have no other message types that we may receive
console.error('Unexpected message type');
break;
}
};
// and register the token update functions on token update
lOriginalDirectorySession.addEventListener(DirectorySessionInterfaceSignal.TokenUpdated, lDirectorySessionTokenUpdate);
lOriginalDataSession.addEventListener(DataSessionInterfaceSignal.TokenUpdated, lDataSessionTokenUpdate);
// register callbacks
registerMessageHandler(onMessage);
// we are ready, send the infos to load a new secondary directory and data session
sendMessage({
type: 'init',
directorySession: lSecondaryDirectorySessionInfo,
dataSession: lSecondaryDataSessionInfo,
// build id is required to create a data session on the correct build
buildId: lOriginalDataSession.getBuildId()
});
};
// the secondary session code
const secondaryCode = () : void =>
{
// create a directory session
const sDirectoryUrl : string = 'https://my_directory:443/directory';
// before connection, this is a "normal" one
const lSecondaryDirectorySession : DirectorySessionInterface = DirectorySessionFactory.CreateDirectorySession(sDirectoryUrl);
// Create a cache to avoid requesting heavy data from the server if data has been retrieved already
const lCache: InfiniteCacheInterface = InfiniteCacheFactory.CreateInfiniteCache();
// the new data session
// we cannot create it right now, we must wait for secondary session info and directory session login
let lSecondaryDataSession : DataSessionInterface;
// hold the open secondary info for future call
let lSecondaryDataSessionInterfaceInfo : SecondaryDataSessionInterfaceInfo;
// the build id we will be connected to
let lDataSessionBuildId : string = '';
// message callback, receive secondary sessions info and tokens
const onMessage : tMessageHandler = (pMessage : any) : void =>
{
switch(pMessage.type)
{
// secondary sessions infos
case 'init':
{
lSecondaryDataSessionInterfaceInfo = pMessage.dataSession;
lDataSessionBuildId = pMessage.buildId;
lSecondaryDirectorySession.asyncOpenSecondaryDirectorySession(pMessage.directorySession).then(
(pOpenResult: AsyncDirectorySessionWaitForLoadedResult) : void => {
if(pOpenResult.reason !== AsyncDirectorySessionWaitForLoadedResultReason.OpenResult_LoginSuccess)
{
// and output some message if the data session opening failed
console.error('directory session opening failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
return;
}
// weird, we should have a build id at this time
if(lDataSessionBuildId.length === 0)
{
// and output some message if the data session creation failed
console.error('data session creation failed, empty build id');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
return;
}
// actually create the DataSessionInterface
lSecondaryDataSession = lSecondaryDirectorySession.createDataSession(lDataSessionBuildId, lCache);
if(lSecondaryDataSession === undefined)
{
// and output some message if the data session creation failed
console.error('data session creation failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
return;
}
// open it in secondary session mode
lSecondaryDataSession.asyncOpenSecondaryDataSession(lSecondaryDataSessionInterfaceInfo).then(
(pDataSessionResult: AsyncDataSessionInterfaceOpenResult) : void =>
{
if(pDataSessionResult !== AsyncDataSessionInterfaceOpenResult.OpenResult_Success)
{
// and output some message if the data session opening failed
console.error('secondary data session opening failed');
// get rid of data
lSecondaryDataSession.dispose();
lSecondaryDataSession = undefined;
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
// and do some fancy things there :)
// we are connected correctly
}
);
}
);
break;
}
case 'directorySessionTokens':
{
// do nothing if the directory session is not connected
if(!lSecondaryDirectorySession.isAuthenticated())
{
return;
}
// and update the tokens
const lResult : boolean = lSecondaryDirectorySession.setTokenValues(pMessage.httpBearer, pMessage.authenticationBearer, pMessage.extendedAuthenticationBearer);
if(!lResult)
{
// and output some message if the token update failed
console.error('set token values failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
break;
}
case 'dataSessionTokens':
{
// do nothing if the data session is not connected nor created
if(lSecondaryDataSession === undefined || !lSecondaryDataSession.isConnected())
{
return;
}
// and update the tokens
const lResult : boolean = lSecondaryDataSession.setTokenValues(pMessage.dataSessionBearer, pMessage.extendedDataSessionBearer);
if(!lResult)
{
// and output some message if the token update failed
console.error('set token values failed');
// and tell the primary session to get rid of the secondary session
sendMessage({ type: 'dataSessionCleanup' });
}
break;
}
default:
// this should not happen, we have no other message types that we may receive
console.error('Unexpected message type');
break;
}
};
// register callbacks
registerMessageHandler(onMessage);
};
// in the primary part
primaryCode();
// in the secondary part
secondaryCode();
A new SecondaryDirectorySessionInterfaceInfo if the DirectorySessionInterface is in primary session mode.
Decodes the hash content and sets the decoded content as session information. If the session content is valid, the life of the session is resumed. This function will fire DirectorySessionInterfaceSignal.LoginSuccess or DirectorySessionInterfaceSignal.LoginFailed depending on the success of the procedure.
Please note that time information is included in the hash, preventing it from being used after some time. The validity period is set by the 3djuump Infinite directory.
This function may return AuthenticationGetURLResult.AuthenticationPending if the authentication mechanism is pending, AuthenticationGetURLResult.DoNotReAuthenticate if the DirectorySessionInterface is already connected, AuthenticationGetURLResult.InvalidSession is an internal error occurred and AuthenticationGetURLResult.InvalidHash is the hash is invalid.
The result of the procedure AuthenticationGetURLResult.AuthenticationPending if the authentication mechanism is pending, AuthenticationGetURLResult.DoNotReAuthenticate if the DirectorySessionInterface is already connected, AuthenticationGetURLResult.InvalidSession is an internal error occurred and AuthenticationGetURLResult.InvalidHash is the hash is invalid.
Sets the content of the bearers.
This function should only be called when the given DirectorySessionInterface is configured as a secondary session (i.e. openSecondaryDirectorySession has been called). The application may listen for the DirectorySessionInterfaceSignal.TokenUpdated signal on the primary DirectorySessionInterface, then call getAuthenticationBearer, getExtendedAuthenticationBearer and getHttpBearer on the primary session, and finally call setTokenValues on the secondary session.
true if the call succeeded.
The DirectorySessionInterface is in charge of the authentication of a user to the 3djuump Infinite architecture, and the initiation of a connection to a 3djuump Infinite proxy.
The DirectorySessionInterface is the formalization of the session to a 3djuump Infinite directory.
The 3djuump Infinite architecture does not feature an internal authentication procedure, but delegates the authentication to an external authentication server by the use of an openid connect protocol.
There is at the moment only 2 ways to authenticate to the 3djuump Infinite directory, by the use of a popup window (getPopupBasedAuthenticationUrl, DirectorySessionFactory.DecodeAuthenticationHash) or a same page authentication (getSamePageAuthenticationUrl, setTokenFromHash).
authenticate.html) with a script that calls DirectorySessionFactory.DecodeAuthenticationHash (see the main page for more information). Depending on your openid configuration, this procedure may be silent for the end-user, with the use of SSO and automatic login. The user may then need to close the authentication tab (or perhaps closed automatically). It is your responsibility to open a new tab (see the code below).2. With the same page authentication. The user will see multiple redirects (the number depending on your openid connect server and its configuration) from the current tab and will be finally redirected to the start page of your application. The last redirect will be done with a hash parameter that contains authentication information. The developer may need to store url parameters in the browser storage (or use the DirectoryAuthenticationOption.applicationData) to be redirected to the final url (see the main page for more information). The authentication procedure is initiated with getSamePageAuthenticationUrl which should return the redirection url to visit, and then setTokenFromHash on the last redirect. The setTokenFromHash will normally send DirectorySessionInterfaceSignal.LoginSuccess asynchronously.
Upon a successful connection, user access rights are retrieved asynchronously with the connection to the DirectorySessionInterfaceSignal.LoginSuccess signal. User access rights are formalized with the ConnectionData object, that contains the list of tags, teams attached to this user, and also the available builds/projects for this user. You can force the refreshing of this information with a call to refreshAccessRightsInfo.
The DirectorySessionInterface is the factory to a DataSessionInterface that allows to choose a specific proxy to connect to, and begin downloading / initializing data.
The same DirectorySessionInterface may be shared upon multiple tabs. In order to do so, one DirectorySessionInterface plays the role of the 'primary session' while others play the role of secondary ones. The secondary session must be opened with openSecondaryDirectorySession, and regularly updated with setTokenValues when the primary DirectorySessionInterface triggers a DirectorySessionInterfaceSignal.TokenUpdated (and bearers are retrieved with getAuthenticationBearer, getExtendedAuthenticationBearer and getHttpBearer).
or asynchronously :
Please see DataSessionInterface for more explanations about sessions.
See