Skip to content

Commit

Permalink
fix #1379 - re-evaluate customUiPath when version number changes
Browse files Browse the repository at this point in the history
  • Loading branch information
oznu committed Jul 9, 2022
1 parent bdb239b commit 757452f
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 8 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## NEXT

### Bug Fixes

* **Backups:** Exclude `.npmrc` files from backups
* **Plugins:** A plugin with a [custom user interfaces](https://github.com/homebridge/plugin-ui-utils) will have it's optional `customUiPath` property re-evaluated when the package version changes ([#1379](https://github.com/oznu/homebridge-config-ui-x/issues/1379))
* **Plugins:** Prevent a plugin using symlink to define a `customUiPath` outside it's root directory

## 4.49.0 (2022-07-08)

### Notable Changes
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "homebridge-config-ui-x",
"displayName": "Homebridge UI",
"version": "4.49.0",
"version": "4.49.1-test.1",
"description": "A web based management, configuration and control platform for Homebridge",
"license": "MIT",
"author": "oznu <dev@oz.nu>",
Expand Down
2 changes: 2 additions & 0 deletions src/modules/backup/backup.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export class BackupService {
'pnpm-lock.yaml', // pnpm
'package.json', // npm
'package-lock.json', // npm
'.npmrc', // npm
'FFmpeg', // ffmpeg
'fdk-aac', // ffmpeg
'.git', // git
Expand Down Expand Up @@ -392,6 +393,7 @@ export class BackupService {
const restoreFilter = [
path.join(this.restoreDirectory, 'storage', 'package.json'),
path.join(this.restoreDirectory, 'storage', 'package-lock.json'),
path.join(this.restoreDirectory, 'storage', '.npmrc'),
];

// restore files
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export class PluginsSettingsUiController {
@Get('/:pluginName/*')
@ApiOperation({ summary: 'Returns the HTML assets for a plugin\'s custom UI' })
@ApiParam({ name: 'pluginName', type: 'string' })
async serveCustomUiAsset(@Res() reply, @Param('pluginName') pluginName, @Param('*') file, @Query('origin') origin: string) {
return await this.pluginSettingsUiService.serveCustomUiAsset(reply, pluginName, file, origin);
async serveCustomUiAsset(@Res() reply, @Param('pluginName') pluginName, @Param('*') file, @Query('origin') origin: string, @Query('v') v?: string) {
return await this.pluginSettingsUiService.serveCustomUiAsset(reply, pluginName, file, origin, v);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { EventEmitter } from 'events';
@Injectable()
export class PluginsSettingsUiService {
private pluginUiMetadataCache = new NodeCache({ stdTTL: 86400 });
private pluginUiLastVersionCache = new NodeCache({ stdTTL: 86400 });

constructor(
private loggerService: Logger,
Expand All @@ -26,12 +27,18 @@ export class PluginsSettingsUiService {
/**
* Serve Custom HTML Assets for a plugin
*/
async serveCustomUiAsset(reply, pluginName: string, assetPath: string, origin: string) {
async serveCustomUiAsset(reply, pluginName: string, assetPath: string, origin: string, version?: string) {
try {
if (!assetPath) {
assetPath = 'index.html';
}

if (assetPath === 'index.html' && version) {
if (version !== this.pluginUiLastVersionCache.get(pluginName)) {
this.pluginUiMetadataCache.del(pluginName);
}
}

const pluginUi: HomebridgePluginUiMetadata = (this.pluginUiMetadataCache.get(pluginName) as any)
|| (await this.getPluginUiMetadata(pluginName));

Expand Down Expand Up @@ -80,6 +87,7 @@ export class PluginsSettingsUiService {
try {
const pluginUi = await this.pluginsService.getPluginUiMetadata(pluginName);
this.pluginUiMetadataCache.set(pluginName, pluginUi);
this.pluginUiLastVersionCache.set(pluginName, pluginUi.plugin.installedVersion);
return pluginUi;
} catch (e) {
this.loggerService.warn(`[${pluginName}] Custom UI:`, e.message);
Expand Down
12 changes: 8 additions & 4 deletions src/modules/plugins/plugins.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -932,14 +932,18 @@ export class PluginsService {
const schema = await fs.readJson(path.resolve(fullPath, 'config.schema.json'));
const customUiPath = path.resolve(fullPath, schema.customUiPath || 'homebridge-ui');

if (!customUiPath.startsWith(fullPath)) {
throw new Error('Custom UI path is outside the plugin root.');
}

const publicPath = path.resolve(customUiPath, 'public');
const serverPath = path.resolve(customUiPath, 'server.js');
const devServer = plugin.private ? schema.customUiDevServer : null;

if (!devServer && !await fs.pathExists(customUiPath)) {
throw new Error('Plugin does not provide a custom UI at expected location: ' + customUiPath);
}

if (!devServer && !(await fs.realpath(customUiPath)).startsWith(await fs.realpath(fullPath))) {
throw new Error('Custom UI path is outside the plugin root: ' + await fs.realpath(customUiPath));
}

if (await fs.pathExists(path.resolve(publicPath, 'index.html')) || devServer) {
return {
devServer,
Expand Down

0 comments on commit 757452f

Please sign in to comment.