05/18 Enhanced codes and functionalities 2

This commit is contained in:
2026-05-18 11:48:31 -04:00
parent fc4145a78e
commit 4364daecef
4 changed files with 45 additions and 16 deletions
+1 -1
View File
@@ -116,7 +116,7 @@ def login():
# Columns do not exist yet — migration pending. Skip lockout check.
db.session.rollback()
if not user or not verify_auth_token(auth_hash, user.master_hash):
if not user or not verify_auth_token(auth_hash, user.master_hash, user=user):
if user:
try:
user.failed_login_count = (user.failed_login_count or 0) + 1
+6 -6
View File
@@ -83,7 +83,7 @@ def create_item():
action='vault_item.create',
resource_type='vault_item',
resource_id=item.id,
detail=f'Created {item_type} item: "{name}"',
detail=f'Created {item_type} item (id={item.id})',
ip_address=client_ip(),
)
db.session.commit()
@@ -144,7 +144,7 @@ def update_item(item_id):
action='vault_item.update',
resource_type='vault_item',
resource_id=item.id,
detail=f'Updated item: "{item.name}"',
detail=f'Updated {item.item_type} item (id={item.id})',
ip_address=client_ip(),
)
db.session.commit()
@@ -162,16 +162,16 @@ def delete_item(item_id):
item = VaultItem.query.filter_by(id=item_id, user_id=g.current_user_id).first()
if not item:
return jsonify({'error': 'Item not found'}), 404
item_name = item.name
item_id = item.id
item_id_saved = item.id
item_type_saved = item.item_type
db.session.delete(item)
db.session.flush()
AuditLog.log(
user_id=g.current_user_id,
action='vault_item.delete',
resource_type='vault_item',
resource_id=item_id,
detail=f'Deleted item: "{item_name}"',
resource_id=item_id_saved,
detail=f'Deleted {item_type_saved} item (id={item_id_saved})',
ip_address=client_ip(),
)
db.session.commit()
+16 -2
View File
@@ -24,10 +24,24 @@ def hash_auth_token(auth_hash: str) -> str:
return ph.hash(auth_hash)
def verify_auth_token(auth_hash: str, stored_hash: str) -> bool:
def verify_auth_token(auth_hash: str, stored_hash: str, user=None) -> bool:
"""
Verify auth_hash against stored Argon2id hash.
If user is provided and the stored hash uses outdated parameters,
the hash is transparently upgraded on successful verification.
Caller must commit the session after this returns True.
"""
ph = PasswordHasher()
try:
return ph.verify(stored_hash, auth_hash)
result = ph.verify(stored_hash, auth_hash)
if result and user is not None and ph.check_needs_rehash(stored_hash):
ph_fresh = PasswordHasher(
time_cost=current_app.config['ARGON2_TIME_COST'],
memory_cost=current_app.config['ARGON2_MEMORY_COST'],
parallelism=current_app.config['ARGON2_PARALLELISM'],
)
user.master_hash = ph_fresh.hash(auth_hash)
return result
except (VerifyMismatchError, VerificationError, InvalidHashError):
return False
+22 -7
View File
@@ -931,13 +931,22 @@ const Vault = (() => {
for (let i = 1; i < lines.length; i++) {
const line = lines[i].trim();
if (!line) continue;
// Simple CSV split — handles quoted fields containing commas.
// RFC 4180-compliant CSV split — handles quoted fields containing commas
// and embedded double-quotes escaped as "".
const cells = [];
let cur = "",
inQuote = false;
for (const ch of line + ",") {
const src = line + ",";
for (let ci = 0; ci < src.length; ci++) {
const ch = src[ci];
if (ch === '"') {
inQuote = !inQuote;
if (inQuote && src[ci + 1] === '"') {
// Escaped quote inside a quoted field: "" → "
cur += '"';
ci++; // skip the second quote
} else {
inQuote = !inQuote;
}
} else if (ch === "," && !inQuote) {
cells.push(cur.trim());
cur = "";
@@ -2856,10 +2865,16 @@ const Vault = (() => {
applyCurrentFilter();
return;
}
const pool = _activeFilter
? _activeFilter.type === "itemType"
? _items.filter((i) => i.item_type === _activeFilter.value)
: _items.filter((i) => i.folder_id === _activeFilter.value)
const pool = !_activeFilter
? _items
: _activeFilter.type === "itemType"
? _items.filter((i) => i.item_type === _activeFilter.value)
: _activeFilter.type === "folder"
? _items.filter((i) => i.folder_id === _activeFilter.value)
: _activeFilter.type === "tag"
? _items.filter((i) =>
(i.plain?.tags || []).includes(_activeFilter.value),
)
: _items;
renderItemList(
pool.filter(