05/18 Enhanced codes and functionalities 2
This commit is contained in:
+1
-1
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user