Legacy App Loader
The Legacy AppLoader was created to enable the loading of most of the current Fusion applications since many of them have not migrated to the defined Fusion framework. Legacy AppLoader has been developed as a Fusion application that provides all the necessary metadata and configuration to the applications that are being loaded.
Fusion Core has provided an @equinor/fusion-framework-legacy-interop
package. This package was functional in the Fusion environment but was not compatible our solution.
It is good to note that we have not provided all information needed according to fusions global environment.
var fusionEnvironment = {
name: 'FPRD', pullRequest: ''
}; // name is provided
var clientId = 'guid'; // is now provided
var domain = ''; // ???
var currentUpn = 'user@equinor.com'; // not provided
var instrumentationKey = 'guid' // not provided
var portalRoles = []; // not provided
var serviceEndpoints = {
"org-chart":"https://fusion-s-org-FPRD.azurewebsites.net",
"meeting-v2":"https://backend-fusion-services-meetings-fprd.radix.equinor.com",
"task":"https://fusion-s-fusiontasks-FPRD.azurewebsites.net",
"people":"https://fusion-s-people-FPRD.azurewebsites.net",
"data-proxy":"https://fusion-s-dataproxy-FPRD.azurewebsites.net",
"projects":"https://fusion-s-projects-FPRD.azurewebsites.net",
"fusiontasks":"https://fusion-s-fusiontasks-FPRD.azurewebsites.net",
"roles":"https://fusion-s-roles-FPRD.azurewebsites.net",
"reports":"https://fusion-s-reports-fprd.azurewebsites.net/",
"context":"https://fusion-s-context-FPRD.azurewebsites.net",
"az-function-utility":"https://fusion-f-utility-FPRD.azurewebsites.net",
"line-org":"https://fusion-s-lineorg-fprd.azurewebsites.net",
"notification":"https://fusion-s-notification-FPRD.azurewebsites.net",
"info-app":"https://fusion-s-infoapp-FPRD.azurewebsites.net",
"bookmarks":"https://fusion-s-bookmarks-fprd.azurewebsites.net",
"contract-personnel":"https://fusion-s-contractpersonnel-fprd.azurewebsites.net",
"apps":"https://fusion-s-apps-fprd.azurewebsites.net"}; // not provided, should be handle from servicediscovery
var fusionPortalClientId = 'guid'; // not provided
var agGridLicenseKey = 'ag-grid key', // is provided, was needed for portal config.
clientId is essential to ensure the authentication flow of applications. Without it, the application may inadvertently trigger an authentication process that utilizes a test client ID, as demonstrated in the code used in the applications below.
export const getFusionAppId = () => {
if ('clientId' in window) {
return (window as any)['clientId'];
}
return '5a842df8-3238-415d-b168-9f16a6a6031b'; // clientId to text/ci environment >.<
};
fusionLegacyEnvIdentifier should always be returned in capital letters , some application check this and are case sensitive
/**
* @deprecated
*/
protected async refreshTokenAsync(resource: string): Promise<string | null> {
DEBUG_LOG &&
console.trace(
`FusionAuthContainer::refreshTokenAsync legacy for resource [${resource}]`
);
const app = this.resolveApp(resource);
if (app && app.clientId === global.clientId) {
const refreshUrl = `/auth/refresh`;
try {
const response = await fetch(refreshUrl, {
credentials: "include",
method: "POST",
});
if (response.status === 200) {
return response.text();
}
} catch (err) {
console.error(err);
}
}
return super.refreshTokenAsync(resource);
}
}
[DisableCors]
[XFrameOptions("DENY")]
[ApiExplorerSettings(IgnoreApi = true)] //these are private endpoints
[Authorize(AuthorizationPolicies.COOKIE)]
[HttpPost("/auth/refresh")]
public async Task<IActionResult> TokenRefresh([FromServices] ITokenProvider tokenProvider)
{
try
{
var token = await tokenProvider.GetAccessTokenAsync();
return Ok(token);
}
catch (AdalSilentTokenAcquisitionException ex) // failed_to_acquire_token_silently
{
return BadRequest(new
{
error = new
{
code = ex.ErrorCode,
message = $"{ex.Message}. Please sign in again."
}
});
}
}
The Fusion legacy system relies on certain packages placed in the global scope within the browser. This approach is intended to reduce the size of application bundles, but it also limits an application's ability to independently manage its dependencies. Furthermore, all legacy applications are using an older version of React compared to the current one.
import React from 'react';
import ReactDOM from 'react-dom';
import * as fusion from '@equinor/fusion';
import * as fusionComponents from '@equinor/fusion-components';
import * as fusionReactStyles from '@equinor/fusion-react-styles';
import * as FusionReactRouter from 'react-router-dom';
declare global {
interface Window {
FusionReact: typeof React;
FusionReactDOM: typeof ReactDOM;
FusionReactRouter: typeof FusionReactRouter;
FusionAPI: typeof fusion;
FusionComponents: typeof fusionComponents;
FusionReactStyles: typeof fusionReactStyles;
clientBaseUri: string;
}
}
export function addGlobalDependencies() {
window['FusionReactDOM'] = ReactDOM;
window['FusionReact'] = React;
window['FusionReactRouter'] = FusionReactRouter;
window['FusionAPI'] = fusion;
window['FusionComponents'] = fusionComponents;
window['FusionReactStyles'] = fusionReactStyles;
}
addGlobalDependencies();
Possible Context Bug
It has been observed that switching contexts with legacy applications may lead to the application loading previous context data. This issue arises due to multiple requests being launched by the application without canceling the previous request. These issues were encountered during testing when navigating between the "ProjectMaster" and "Facility" contexts in the legacy garden "CC-applications." As a result, a fix has not been implemented, but the area and potential solution to address the issue from a portal perspective have been identified. It's important to note that this solution will not resolve underlying issues with application design but will fix the issue of portal and application applying context in sequence as this is what causes the issue.