UNPKG

homebridge-config-ui-x

Version:

A web based management, configuration and control platform for Homebridge.

133 lines • 6.95 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; import process from 'node:process'; import { Controller, Get, Inject, NotFoundException, Param, Post, Query, Req, Res, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { ApiBearerAuth, ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger'; import { API_PREFIX } from '../../../core/api.constants.js'; import { AdminGuard } from '../../../core/auth/guards/admin.guard.js'; import { PluginsSettingsUiTicketService } from './plugins-settings-ui-ticket.service.js'; import { PluginsSettingsUiService } from './plugins-settings-ui.service.js'; let PluginsSettingsUiController = class PluginsSettingsUiController { pluginSettingsUiService; ticketService; constructor(pluginSettingsUiService, ticketService) { this.pluginSettingsUiService = pluginSettingsUiService; this.ticketService = ticketService; } async issueTicket(request, pluginName) { await this.pluginSettingsUiService.getPluginUiMetadata(pluginName); return { ticket: this.ticketService.issue(pluginName, request.user.username, request.headers?.origin, request.headers?.host), expiresIn: 60, }; } async serveCustomUiIndex(request, reply, pluginName, ticket, version) { let uiOrigin; let assetSession; try { const claims = this.ticketService.consume(ticket, pluginName); uiOrigin = claims.uiOrigin; assetSession = this.ticketService.issueAssetSession(pluginName, claims.username, claims.uiOrigin); } catch { const existing = this.ticketService.validateAssetSession(this.ticketService.extractAssetSession(request.headers?.cookie), pluginName); uiOrigin = existing.uiOrigin; assetSession = existing.token; } this.setAssetSessionCookie(request, reply, assetSession); reply.header('Cache-Control', 'no-store, private'); reply.header('Pragma', 'no-cache'); reply.header('Referrer-Policy', 'no-referrer'); return await this.pluginSettingsUiService.serveCustomUiAsset(reply, pluginName, 'index.html', uiOrigin, version); } revokeAssetSession(request, reply, pluginName) { this.ticketService.revokeUserPlugin(request.user.username, pluginName); this.setAssetSessionCookie(request, reply, '', 0); return { status: 'OK' }; } async serveCustomUiAsset(request, reply, pluginName, file, v) { if (!file || /(?:^|\/)index\.html$/i.test(file) || /\.(?:html?|xhtml)$/i.test(file)) { throw new NotFoundException(); } const isDevelopmentSourceMap = process.env.UIX_DEVELOPMENT === '1' && file.toLowerCase().endsWith('.map'); if (!isDevelopmentSourceMap) { const session = this.ticketService.validateAssetSession(this.ticketService.extractAssetSession(request.headers?.cookie), pluginName); this.setAssetSessionCookie(request, reply, session.token); } return await this.pluginSettingsUiService.serveCustomUiAsset(reply, pluginName, file, '', v); } setAssetSessionCookie(request, reply, token, maxAge = PluginsSettingsUiTicketService.assetSessionTtl) { const cookiePath = `${API_PREFIX}/plugins/settings-ui/${encodeURIComponent(request.params.pluginName)}/`; const secure = request.protocol === 'https' ? '; Secure' : ''; reply.header('Set-Cookie', `hb-plugin-ui=${token}; HttpOnly; SameSite=Strict; Path=${cookiePath}; Max-Age=${maxAge}${secure}`); } }; __decorate([ Post('/:pluginName/ticket'), UseGuards(AuthGuard('jwt'), AdminGuard), ApiBearerAuth(), ApiOperation({ summary: 'Issues a single-use ticket for a plugin custom UI.' }), __param(0, Req()), __param(1, Param('pluginName')), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String]), __metadata("design:returntype", Promise) ], PluginsSettingsUiController.prototype, "issueTicket", null); __decorate([ Get('/:pluginName/index.html'), ApiOperation({ summary: 'Redeems a single-use ticket and returns a plugin custom UI.' }), __param(0, Req()), __param(1, Res()), __param(2, Param('pluginName')), __param(3, Query('ticket')), __param(4, Query('v')), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object, String, String, String]), __metadata("design:returntype", Promise) ], PluginsSettingsUiController.prototype, "serveCustomUiIndex", null); __decorate([ Post('/:pluginName/session/revoke'), UseGuards(AuthGuard('jwt'), AdminGuard), ApiBearerAuth(), ApiOperation({ summary: 'Revokes the active custom-UI asset session.' }), __param(0, Req()), __param(1, Res({ passthrough: true })), __param(2, Param('pluginName')), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object, String]), __metadata("design:returntype", void 0) ], PluginsSettingsUiController.prototype, "revokeAssetSession", null); __decorate([ Get('/:pluginName/*'), ApiOperation({ summary: 'Returns a static asset for a plugin custom UI.' }), ApiParam({ name: 'pluginName', type: 'string' }), __param(0, Req()), __param(1, Res()), __param(2, Param('pluginName')), __param(3, Param('*')), __param(4, Query('v')), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object, Object, Object, String]), __metadata("design:returntype", Promise) ], PluginsSettingsUiController.prototype, "serveCustomUiAsset", null); PluginsSettingsUiController = __decorate([ ApiTags('Plugins'), Controller('plugins/settings-ui'), __param(0, Inject(PluginsSettingsUiService)), __param(1, Inject(PluginsSettingsUiTicketService)), __metadata("design:paramtypes", [PluginsSettingsUiService, PluginsSettingsUiTicketService]) ], PluginsSettingsUiController); export { PluginsSettingsUiController }; //# sourceMappingURL=plugins-settings-ui.controller.js.map