mirror of
https://github.com/finos/SymphonyElectron.git
synced 2024-11-21 08:34:40 -06:00
SDA-4182: Add GPOs to auto update channel (#1896)
This commit is contained in:
parent
7d23cd60f8
commit
15056f16ff
@ -3,6 +3,7 @@
|
|||||||
"autoUpdateUrl": "",
|
"autoUpdateUrl": "",
|
||||||
"autoUpdateChannel": "latest",
|
"autoUpdateChannel": "latest",
|
||||||
"isAutoUpdateEnabled": true,
|
"isAutoUpdateEnabled": true,
|
||||||
|
"forceAutoUpdate": false,
|
||||||
"autoUpdateCheckInterval": "30",
|
"autoUpdateCheckInterval": "30",
|
||||||
"enableBrowserLogin": false,
|
"enableBrowserLogin": false,
|
||||||
"browserLoginAutoConnect": false,
|
"browserLoginAutoConnect": false,
|
||||||
|
44
spec/registryHandler.spec.ts
Normal file
44
spec/registryHandler.spec.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { retrieveWindowsRegistry } from '../src/app/registry-handler';
|
||||||
|
import {
|
||||||
|
EChannelRegistry,
|
||||||
|
RegistryStore,
|
||||||
|
} from '../src/app/stores/registry-store';
|
||||||
|
|
||||||
|
let mockChannel = { value: '', type: 'REG_SZ' };
|
||||||
|
|
||||||
|
jest.mock('winreg', () => {
|
||||||
|
return jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
get: (_file, callback) => callback(null, mockChannel),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.mock('../src/common/env', () => {
|
||||||
|
return {
|
||||||
|
isWindowsOS: true,
|
||||||
|
isLinux: false,
|
||||||
|
isMac: false,
|
||||||
|
isDevEnv: true,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Windows Registry', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks().resetModules();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('it should return channel - latest', async () => {
|
||||||
|
mockChannel.value = 'latest';
|
||||||
|
await retrieveWindowsRegistry();
|
||||||
|
const registry = RegistryStore.getRegistry();
|
||||||
|
expect(registry.currentChannel).toBe(EChannelRegistry.LATEST);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('it should return channel - beta', async () => {
|
||||||
|
mockChannel.value = 'beta';
|
||||||
|
await retrieveWindowsRegistry();
|
||||||
|
const registry = RegistryStore.getRegistry();
|
||||||
|
expect(registry.currentChannel).toBe(EChannelRegistry.BETA);
|
||||||
|
});
|
||||||
|
});
|
@ -7,6 +7,8 @@ import { logger } from '../common/logger';
|
|||||||
import { isUrl } from '../common/utils';
|
import { isUrl } from '../common/utils';
|
||||||
import { whitelistHandler } from '../common/whitelist-handler';
|
import { whitelistHandler } from '../common/whitelist-handler';
|
||||||
import { config } from './config-handler';
|
import { config } from './config-handler';
|
||||||
|
import { retrieveWindowsRegistry } from './registry-handler';
|
||||||
|
import { EChannelRegistry, RegistryStore } from './stores/registry-store';
|
||||||
import { windowHandler } from './window-handler';
|
import { windowHandler } from './window-handler';
|
||||||
|
|
||||||
const DEFAULT_AUTO_UPDATE_CHANNEL = 'client-bff/sda-update';
|
const DEFAULT_AUTO_UPDATE_CHANNEL = 'client-bff/sda-update';
|
||||||
@ -23,122 +25,139 @@ export class AutoUpdate {
|
|||||||
private autoUpdateTrigger: AutoUpdateTrigger | undefined = undefined;
|
private autoUpdateTrigger: AutoUpdateTrigger | undefined = undefined;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
const opts = this.getGenericServerOptions();
|
this.getGenericServerOptions().then((opts) => {
|
||||||
if (isMac) {
|
if (isMac) {
|
||||||
this.autoUpdater = new MacUpdater(opts);
|
this.autoUpdater = new MacUpdater(opts);
|
||||||
} else if (isWindowsOS) {
|
} else if (isWindowsOS) {
|
||||||
this.autoUpdater = new NsisUpdater(opts);
|
this.autoUpdater = new NsisUpdater(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.autoUpdater) {
|
if (this.autoUpdater) {
|
||||||
this.autoUpdater.logger = electronLog;
|
this.autoUpdater.logger = electronLog;
|
||||||
this.autoUpdater.autoDownload = false;
|
this.autoUpdater.autoDownload = false;
|
||||||
this.autoUpdater.autoInstallOnAppQuit = true;
|
this.autoUpdater.autoInstallOnAppQuit = true;
|
||||||
this.autoUpdater.allowDowngrade = true;
|
this.autoUpdater.allowDowngrade = true;
|
||||||
|
|
||||||
this.autoUpdater.on('update-not-available', () => {
|
this.autoUpdater.on('update-not-available', () => {
|
||||||
if (this.autoUpdateTrigger === AutoUpdateTrigger.AUTOMATED) {
|
if (this.autoUpdateTrigger === AutoUpdateTrigger.AUTOMATED) {
|
||||||
logger.info(
|
logger.info(
|
||||||
'auto-update-handler: no update available found with automatic check',
|
'auto-update-handler: no update available found with automatic check',
|
||||||
);
|
);
|
||||||
|
this.autoUpdateTrigger = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const mainWebContents = windowHandler.mainWebContents;
|
||||||
|
// Display client banner
|
||||||
|
if (mainWebContents && !mainWebContents.isDestroyed()) {
|
||||||
|
mainWebContents.send('display-client-banner', {
|
||||||
|
reason: 'autoUpdate',
|
||||||
|
action: 'update-not-available',
|
||||||
|
});
|
||||||
|
}
|
||||||
this.autoUpdateTrigger = undefined;
|
this.autoUpdateTrigger = undefined;
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
const mainWebContents = windowHandler.mainWebContents;
|
|
||||||
// Display client banner
|
|
||||||
if (mainWebContents && !mainWebContents.isDestroyed()) {
|
|
||||||
mainWebContents.send('display-client-banner', {
|
|
||||||
reason: 'autoUpdate',
|
|
||||||
action: 'update-not-available',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.autoUpdateTrigger = undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
const { autoUpdateChannel } = config.getConfigFields([
|
const { autoUpdateChannel } = config.getConfigFields([
|
||||||
'autoUpdateChannel',
|
'autoUpdateChannel',
|
||||||
]);
|
]);
|
||||||
const { installVariant } = config.getConfigFields(['installVariant']);
|
let finalAutoUpdateChannel = autoUpdateChannel;
|
||||||
this.autoUpdater.on('update-available', (info) => {
|
|
||||||
const mainWebContents = windowHandler.mainWebContents;
|
|
||||||
// Display client banner
|
|
||||||
if (mainWebContents && !mainWebContents.isDestroyed()) {
|
|
||||||
mainWebContents.send('display-client-banner', {
|
|
||||||
reason: 'autoUpdate',
|
|
||||||
action: 'update-available',
|
|
||||||
data: {
|
|
||||||
...info,
|
|
||||||
autoUpdateTrigger: this.autoUpdateTrigger,
|
|
||||||
autoUpdateChannel,
|
|
||||||
installVariant,
|
|
||||||
channelConfigLocation: null,
|
|
||||||
sessionStartDatetime: null,
|
|
||||||
machineStartDatetime: null,
|
|
||||||
machineId: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.autoUpdater.on('download-progress', (info) => {
|
if (isWindowsOS) {
|
||||||
const mainWebContents = windowHandler.mainWebContents;
|
const registryAutoUpdate = RegistryStore.getRegistry();
|
||||||
// Display client banner
|
const identifiedChannelFromRegistry = [
|
||||||
if (
|
EChannelRegistry.BETA,
|
||||||
mainWebContents &&
|
EChannelRegistry.LATEST,
|
||||||
!mainWebContents.isDestroyed() &&
|
].includes(registryAutoUpdate.currentChannel)
|
||||||
!this.didPublishDownloadProgress
|
? registryAutoUpdate.currentChannel
|
||||||
) {
|
: '';
|
||||||
mainWebContents.send('display-client-banner', {
|
|
||||||
reason: 'autoUpdate',
|
|
||||||
action: 'download-progress',
|
|
||||||
data: {
|
|
||||||
...info,
|
|
||||||
autoUpdateTrigger: this.autoUpdateTrigger,
|
|
||||||
autoUpdateChannel,
|
|
||||||
installVariant,
|
|
||||||
channelConfigLocation: null,
|
|
||||||
sessionStartDatetime: null,
|
|
||||||
machineStartDatetime: null,
|
|
||||||
machineId: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.didPublishDownloadProgress = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.autoUpdater.on('update-downloaded', (info) => {
|
if (identifiedChannelFromRegistry) {
|
||||||
this.isUpdateAvailable = true;
|
finalAutoUpdateChannel = identifiedChannelFromRegistry;
|
||||||
const mainWebContents = windowHandler.mainWebContents;
|
}
|
||||||
// Display client banner
|
|
||||||
if (mainWebContents && !mainWebContents.isDestroyed()) {
|
|
||||||
mainWebContents.send('display-client-banner', {
|
|
||||||
reason: 'autoUpdate',
|
|
||||||
action: 'update-downloaded',
|
|
||||||
data: {
|
|
||||||
...info,
|
|
||||||
autoUpdateTrigger: this.autoUpdateTrigger,
|
|
||||||
autoUpdateChannel,
|
|
||||||
installVariant,
|
|
||||||
channelConfigLocation: null,
|
|
||||||
sessionStartDatetime: null,
|
|
||||||
machineStartDatetime: null,
|
|
||||||
machineId: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (isMac) {
|
|
||||||
config.backupGlobalConfig();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.autoUpdater.on('error', (error) => {
|
const { installVariant } = config.getConfigFields(['installVariant']);
|
||||||
this.autoUpdateTrigger = undefined;
|
this.autoUpdater.on('update-available', (info) => {
|
||||||
logger.error(
|
const mainWebContents = windowHandler.mainWebContents;
|
||||||
'auto-update-handler: Error occurred while updating. ',
|
// Display client banner
|
||||||
error,
|
if (mainWebContents && !mainWebContents.isDestroyed()) {
|
||||||
);
|
mainWebContents.send('display-client-banner', {
|
||||||
});
|
reason: 'autoUpdate',
|
||||||
}
|
action: 'update-available',
|
||||||
|
data: {
|
||||||
|
...info,
|
||||||
|
autoUpdateTrigger: this.autoUpdateTrigger,
|
||||||
|
autoUpdateChannel: finalAutoUpdateChannel,
|
||||||
|
installVariant,
|
||||||
|
channelConfigLocation: null,
|
||||||
|
sessionStartDatetime: null,
|
||||||
|
machineStartDatetime: null,
|
||||||
|
machineId: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.autoUpdater.on('download-progress', (info) => {
|
||||||
|
const mainWebContents = windowHandler.mainWebContents;
|
||||||
|
// Display client banner
|
||||||
|
if (
|
||||||
|
mainWebContents &&
|
||||||
|
!mainWebContents.isDestroyed() &&
|
||||||
|
!this.didPublishDownloadProgress
|
||||||
|
) {
|
||||||
|
mainWebContents.send('display-client-banner', {
|
||||||
|
reason: 'autoUpdate',
|
||||||
|
action: 'download-progress',
|
||||||
|
data: {
|
||||||
|
...info,
|
||||||
|
autoUpdateTrigger: this.autoUpdateTrigger,
|
||||||
|
autoUpdateChannel: finalAutoUpdateChannel,
|
||||||
|
installVariant,
|
||||||
|
channelConfigLocation: null,
|
||||||
|
sessionStartDatetime: null,
|
||||||
|
machineStartDatetime: null,
|
||||||
|
machineId: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.didPublishDownloadProgress = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.autoUpdater.on('update-downloaded', (info) => {
|
||||||
|
this.isUpdateAvailable = true;
|
||||||
|
const mainWebContents = windowHandler.mainWebContents;
|
||||||
|
// Display client banner
|
||||||
|
if (mainWebContents && !mainWebContents.isDestroyed()) {
|
||||||
|
mainWebContents.send('display-client-banner', {
|
||||||
|
reason: 'autoUpdate',
|
||||||
|
action: 'update-downloaded',
|
||||||
|
data: {
|
||||||
|
...info,
|
||||||
|
autoUpdateTrigger: this.autoUpdateTrigger,
|
||||||
|
autoUpdateChannel: finalAutoUpdateChannel,
|
||||||
|
installVariant,
|
||||||
|
channelConfigLocation: null,
|
||||||
|
sessionStartDatetime: null,
|
||||||
|
machineStartDatetime: null,
|
||||||
|
machineId: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (isMac) {
|
||||||
|
config.backupGlobalConfig();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.autoUpdater.on('error', (error) => {
|
||||||
|
this.autoUpdateTrigger = undefined;
|
||||||
|
logger.error(
|
||||||
|
'auto-update-handler: Error occurred while updating. ',
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -173,7 +192,7 @@ export class AutoUpdate {
|
|||||||
this.autoUpdateTrigger = trigger;
|
this.autoUpdateTrigger = trigger;
|
||||||
logger.info('auto-update-handler: Checking for updates', trigger);
|
logger.info('auto-update-handler: Checking for updates', trigger);
|
||||||
if (this.autoUpdater) {
|
if (this.autoUpdater) {
|
||||||
const opts: GenericServerOptions = this.getGenericServerOptions();
|
const opts: GenericServerOptions = await this.getGenericServerOptions();
|
||||||
this.autoUpdater.setFeedURL(opts);
|
this.autoUpdater.setFeedURL(opts);
|
||||||
const updateCheckResult = await this.autoUpdater.checkForUpdates();
|
const updateCheckResult = await this.autoUpdater.checkForUpdates();
|
||||||
logger.info('auto-update-handler: ', updateCheckResult);
|
logger.info('auto-update-handler: ', updateCheckResult);
|
||||||
@ -221,16 +240,31 @@ export class AutoUpdate {
|
|||||||
return updateUrl;
|
return updateUrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
private getGenericServerOptions = (): GenericServerOptions => {
|
private getGenericServerOptions = async (): Promise<GenericServerOptions> => {
|
||||||
let userAutoUpdateChannel;
|
let userAutoUpdateChannel;
|
||||||
const { autoUpdateChannel, betaAutoUpdateChannelEnabled } =
|
const { autoUpdateChannel, betaAutoUpdateChannelEnabled } =
|
||||||
config.getConfigFields([
|
config.getConfigFields([
|
||||||
'autoUpdateChannel',
|
'autoUpdateChannel',
|
||||||
'betaAutoUpdateChannelEnabled',
|
'betaAutoUpdateChannelEnabled',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
userAutoUpdateChannel = betaAutoUpdateChannelEnabled
|
userAutoUpdateChannel = betaAutoUpdateChannelEnabled
|
||||||
? 'beta'
|
? 'beta'
|
||||||
: autoUpdateChannel;
|
: autoUpdateChannel;
|
||||||
|
if (isWindowsOS) {
|
||||||
|
await retrieveWindowsRegistry();
|
||||||
|
const registryAutoUpdate = RegistryStore.getRegistry();
|
||||||
|
const identifiedChannelFromRegistry = [
|
||||||
|
EChannelRegistry.BETA,
|
||||||
|
EChannelRegistry.LATEST,
|
||||||
|
].includes(registryAutoUpdate.currentChannel)
|
||||||
|
? registryAutoUpdate.currentChannel
|
||||||
|
: '';
|
||||||
|
if (identifiedChannelFromRegistry) {
|
||||||
|
userAutoUpdateChannel = identifiedChannelFromRegistry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger.info(`auto-update-handler: using channel ${userAutoUpdateChannel}`);
|
logger.info(`auto-update-handler: using channel ${userAutoUpdateChannel}`);
|
||||||
|
|
||||||
const opts: GenericServerOptions = {
|
const opts: GenericServerOptions = {
|
||||||
|
61
src/app/registry-handler.ts
Normal file
61
src/app/registry-handler.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { logger } from '../common/logger';
|
||||||
|
import { RegistryStore } from './stores/registry-store';
|
||||||
|
|
||||||
|
enum RegistryValueType {
|
||||||
|
REG_SZ = 'REG_SZ',
|
||||||
|
}
|
||||||
|
|
||||||
|
const CHANNEL_NEST_LOCATION = '\\SOFTWARE\\Policies\\Symphony\\Update';
|
||||||
|
const CHANNEL_KEY = 'channel';
|
||||||
|
|
||||||
|
export const retrieveWindowsRegistry = async (): Promise<string> => {
|
||||||
|
const Registry = require('winreg');
|
||||||
|
const registryLocalStore = RegistryStore;
|
||||||
|
const fetchLogic = (err, channel) => {
|
||||||
|
if (err) {
|
||||||
|
logger.info('registry-handler: error occurred. Details: ', err);
|
||||||
|
|
||||||
|
return 'An error has occurred';
|
||||||
|
} else {
|
||||||
|
if (channel.type === RegistryValueType.REG_SZ) {
|
||||||
|
registryLocalStore.setRegistry({ currentChannel: channel.value });
|
||||||
|
logger.info(
|
||||||
|
'registry-handler: value retrieved successfully, send to Registry Store',
|
||||||
|
);
|
||||||
|
|
||||||
|
return channel.value;
|
||||||
|
} else {
|
||||||
|
logger.info(
|
||||||
|
'registry-handler: the value was looked for did not exist or its VALUE_TYPE is incorrect',
|
||||||
|
);
|
||||||
|
|
||||||
|
return 'Key Value doesnt exist';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const regKeyLocal = new Registry({
|
||||||
|
hive: Registry.HKLM,
|
||||||
|
key: CHANNEL_NEST_LOCATION,
|
||||||
|
});
|
||||||
|
|
||||||
|
const regKeyUser = new Registry({
|
||||||
|
hive: Registry.HKCU,
|
||||||
|
key: CHANNEL_NEST_LOCATION,
|
||||||
|
});
|
||||||
|
|
||||||
|
return regKeyUser.get(CHANNEL_KEY, (error, channel) => {
|
||||||
|
if (error && !channel) {
|
||||||
|
regKeyLocal.get(CHANNEL_KEY, (err, localChannel) => {
|
||||||
|
return fetchLogic(err, localChannel);
|
||||||
|
});
|
||||||
|
} else if (channel.type === RegistryValueType.REG_SZ) {
|
||||||
|
registryLocalStore.setRegistry({ currentChannel: channel.value });
|
||||||
|
logger.info(
|
||||||
|
'registry-handler: value retrieved successfully, send to Registry Store',
|
||||||
|
);
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
28
src/app/stores/registry-store.ts
Normal file
28
src/app/stores/registry-store.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
export interface IRegistry {
|
||||||
|
currentChannel: string | 'beta' | 'latest';
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EChannelRegistry = {
|
||||||
|
/**
|
||||||
|
* Has higher authority over autoUpdateChannel, utilized to set Update Channel to LATEST
|
||||||
|
*/
|
||||||
|
LATEST: 'latest',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has higher authority over autoUpdateChannel, utilized to set Update Channel to BETA
|
||||||
|
*/
|
||||||
|
BETA: 'beta',
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registry {
|
||||||
|
private registry: IRegistry = { currentChannel: '' };
|
||||||
|
public getRegistry = (): IRegistry => {
|
||||||
|
return { ...this.registry };
|
||||||
|
};
|
||||||
|
|
||||||
|
public setRegistry = (newRegistry: IRegistry) => {
|
||||||
|
this.registry = { ...this.registry, ...newRegistry };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RegistryStore = new Registry();
|
Loading…
Reference in New Issue
Block a user