feat(ext-api): chave mestra + x-nw-email (middleware REST + WS bridge)
Satélite confiável acessa a conta de qualquer email via EXT_MASTER_KEY: - apikey-auth: helpers isMasterKey/resolveMasterEmail resolvem o tenant pelo User.email; middleware REST refatorado para usá-los. - ws-bridge: handshake do /api/ext/v1/stream trata a chave mestra + x-nw-email (antes só tabela apiKey → o túnel WS tomava 401). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -43,7 +43,20 @@ function buildWsBridge(httpServer, prisma, hooks) {
|
||||
}
|
||||
let tenantId;
|
||||
try {
|
||||
tenantId = await (0, apikey_auth_1.resolveApiKey)(prisma, apiKey);
|
||||
// Chave mestra → resolve o tenant pelo x-nw-email do handshake (o túnel do
|
||||
// satélite injeta o email do usuário autenticado). Chave normal → tabela apiKey.
|
||||
if ((0, apikey_auth_1.isMasterKey)(apiKey)) {
|
||||
const email = req.headers['x-nw-email']?.trim().toLowerCase();
|
||||
if (!email) {
|
||||
socket.write('HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nx-nw-email ausente (chave mestra)');
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
tenantId = await (0, apikey_auth_1.resolveMasterEmail)(prisma, email);
|
||||
}
|
||||
else {
|
||||
tenantId = await (0, apikey_auth_1.resolveApiKey)(prisma, apiKey);
|
||||
}
|
||||
}
|
||||
catch {
|
||||
socket.write('HTTP/1.1 500 Internal Server Error\r\n\r\n');
|
||||
@@ -51,7 +64,7 @@ function buildWsBridge(httpServer, prisma, hooks) {
|
||||
return;
|
||||
}
|
||||
if (!tenantId) {
|
||||
socket.write('HTTP/1.1 401 Unauthorized\r\nContent-Type: text/plain\r\n\r\nChave inválida, inativa ou expirada');
|
||||
socket.write('HTTP/1.1 401 Unauthorized\r\nContent-Type: text/plain\r\n\r\nChave inválida/inativa ou conta não encontrada');
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user