feat: version 2.7.0 -- menu Contraseñas (repositorio de credenciales privado)
Nuevo modulo backend/src/modules/vault/: contraseña y notas cifradas en el servidor (AES-256-GCM, mismo mecanismo ya usado para la clave SMTP). Acceso al menu protegido con un PIN de 4 digitos independiente del login (token corto propio, header X-Vault-Token, nunca el JWT de sesion). El PIN no participa del cifrado -- cambiarlo o restablecerlo por correo nunca afecta las contraseñas ya guardadas. Privado por usuario, sin excepcion. Cada accion sensible (crear/editar/eliminar/ revelar/desbloquear) queda en audit_log. Compartir con otro usuario queda para una proxima version. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,8 +9,8 @@ function getToken() {
|
||||
return localStorage.getItem('plc_token');
|
||||
}
|
||||
|
||||
async function request(method, path, { body, isForm } = {}) {
|
||||
const headers = {};
|
||||
async function request(method, path, { body, isForm, extraHeaders } = {}) {
|
||||
const headers = { ...extraHeaders };
|
||||
const token = getToken();
|
||||
if (token) headers.Authorization = `Bearer ${token}`;
|
||||
if (!isForm && body !== undefined) headers['Content-Type'] = 'application/json';
|
||||
@@ -38,11 +38,11 @@ async function request(method, path, { body, isForm } = {}) {
|
||||
}
|
||||
|
||||
export const api = {
|
||||
get: (path) => request('GET', path),
|
||||
post: (path, body) => request('POST', path, { body }),
|
||||
put: (path, body) => request('PUT', path, { body }),
|
||||
get: (path, extraHeaders) => request('GET', path, { extraHeaders }),
|
||||
post: (path, body, extraHeaders) => request('POST', path, { body, extraHeaders }),
|
||||
put: (path, body, extraHeaders) => request('PUT', path, { body, extraHeaders }),
|
||||
patch: (path, body) => request('PATCH', path, { body }),
|
||||
delete: (path) => request('DELETE', path),
|
||||
delete: (path, extraHeaders) => request('DELETE', path, { extraHeaders }),
|
||||
postForm: (path, formData) => request('POST', path, { body: formData, isForm: true }),
|
||||
putForm: (path, formData) => request('PUT', path, { body: formData, isForm: true }),
|
||||
setToken: (token) => {
|
||||
|
||||
Reference in New Issue
Block a user