mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-08 09:54:26 +00:00
feat(host-console): gate Host Console behind Admiral tier (#277)
* feat(host-console): gate Host Console behind Admiral tier Move the Host Console from the Community (free) tier to Admiral, enforcing the gate at every layer: UI nav visibility, AdmiralGate wrapper, POST /api/system/console-token endpoint, and the WebSocket upgrade handler for /api/system/host-console. * test(auth): mock Admiral license for console-token test The console-token endpoint now requires Admiral tier. Mock LicenseService in the test to return pro/team so the happy-path test passes in CI where no license is activated.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Tests for authentication: login, rate limiting, and auth middleware.
|
||||
*/
|
||||
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||
import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
|
||||
import request from 'supertest';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { setupTestDb, cleanupTestDb, TEST_USERNAME, TEST_PASSWORD, TEST_JWT_SECRET } from './helpers/setupTestDb';
|
||||
@@ -96,6 +96,17 @@ describe('authMiddleware', () => {
|
||||
// ─── Protected endpoint: console-token ───────────────────────────────────────
|
||||
|
||||
describe('POST /api/system/console-token', () => {
|
||||
// Console-token requires Admiral tier — mock LicenseService for the happy-path test
|
||||
beforeAll(async () => {
|
||||
const { LicenseService } = await import('../services/LicenseService');
|
||||
vi.spyOn(LicenseService.getInstance(), 'getTier').mockReturnValue('pro');
|
||||
vi.spyOn(LicenseService.getInstance(), 'getVariant').mockReturnValue('team');
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('returns 401 without authentication (was a security bug - C1 fix)', async () => {
|
||||
const res = await request(app).post('/api/system/console-token');
|
||||
expect(res.status).toBe(401);
|
||||
|
||||
@@ -2316,6 +2316,13 @@ server.on('upgrade', async (req, socket, head) => {
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
// Admiral license gate — host console requires Pro (team variant)
|
||||
const ls = LicenseService.getInstance();
|
||||
if (ls.getTier() !== 'pro' || ls.getVariant() !== 'team') {
|
||||
socket.write('HTTP/1.1 403 Forbidden\r\n\r\n');
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
const hostConsoleWss = new WebSocketServer({ noServer: true });
|
||||
hostConsoleWss.handleUpgrade(req, socket, head, (ws) => {
|
||||
hostConsoleWss.close();
|
||||
@@ -3362,6 +3369,7 @@ app.post('/api/system/console-token', authMiddleware, (req: Request, res: Respon
|
||||
return;
|
||||
}
|
||||
if (!requireAdmin(req, res)) return;
|
||||
if (!requireAdmiral(req, res)) return;
|
||||
try {
|
||||
const settings = DatabaseService.getInstance().getGlobalSettings();
|
||||
const jwtSecret = settings.auth_jwt_secret;
|
||||
|
||||
Reference in New Issue
Block a user