04/26 Enhanced functionalities
This commit is contained in:
@@ -137,3 +137,84 @@ def delete_item(item_id):
|
||||
)
|
||||
db.session.commit()
|
||||
return jsonify({'message': 'Item deleted'}), 200
|
||||
|
||||
|
||||
# ── Import / Export ───────────────────────────────────────────────────────────
|
||||
|
||||
@vault_bp.route('/export', methods=['GET'])
|
||||
@require_jwt
|
||||
def export_items():
|
||||
"""
|
||||
Return all vault items as an encrypted JSON export payload.
|
||||
The client receives raw encrypted blobs and wraps them in a
|
||||
signed JSON envelope — the server never sees plaintext.
|
||||
Each object: { id, name, item_type, folder_id, enc_data, iv, enc_name, iv_name,
|
||||
created_at, updated_at }
|
||||
"""
|
||||
items = VaultItem.query.filter_by(user_id=g.current_user_id).order_by(
|
||||
VaultItem.name.asc()
|
||||
).all()
|
||||
AuditLog.log(
|
||||
user_id=g.current_user_id,
|
||||
action='vault_item.export',
|
||||
resource_type='vault_item',
|
||||
resource_id=None,
|
||||
detail=f'Exported {len(items)} vault item(s)',
|
||||
ip_address=_client_ip(),
|
||||
)
|
||||
db.session.commit()
|
||||
return jsonify([item.to_dict() for item in items]), 200
|
||||
|
||||
|
||||
@vault_bp.route('/import', methods=['POST'])
|
||||
@require_jwt
|
||||
def import_items():
|
||||
"""
|
||||
Bulk-import pre-encrypted vault items.
|
||||
Accepts a JSON array of objects matching the POST /api/vault schema.
|
||||
Items are imported as-is — the server stores encrypted blobs only.
|
||||
Duplicate detection is left to the client.
|
||||
Returns { imported: N, skipped: N } where skipped = malformed rows.
|
||||
"""
|
||||
data = request.get_json(silent=True) or []
|
||||
if not isinstance(data, list):
|
||||
return jsonify({'error': 'Request body must be a JSON array'}), 400
|
||||
|
||||
imported = 0
|
||||
skipped = 0
|
||||
for row in data:
|
||||
name = (row.get('name') or '').strip()
|
||||
item_type = row.get('item_type', 'password')
|
||||
enc_data = row.get('enc_data', '')
|
||||
iv = row.get('iv', '')
|
||||
if not name or item_type not in VALID_TYPES or not enc_data or not iv:
|
||||
skipped += 1
|
||||
continue
|
||||
folder_id = row.get('folder_id')
|
||||
enc_name = row.get('enc_name') or None
|
||||
iv_name = row.get('iv_name') or None
|
||||
item = VaultItem(
|
||||
user_id=g.current_user_id,
|
||||
folder_id=folder_id,
|
||||
item_type=item_type,
|
||||
name=name,
|
||||
enc_data=enc_data,
|
||||
iv=iv,
|
||||
enc_name=enc_name,
|
||||
iv_name=iv_name,
|
||||
)
|
||||
db.session.add(item)
|
||||
imported += 1
|
||||
|
||||
if imported:
|
||||
db.session.flush()
|
||||
AuditLog.log(
|
||||
user_id=g.current_user_id,
|
||||
action='vault_item.import',
|
||||
resource_type='vault_item',
|
||||
resource_id=None,
|
||||
detail=f'Imported {imported} item(s), skipped {skipped} malformed row(s)',
|
||||
ip_address=_client_ip(),
|
||||
)
|
||||
db.session.commit()
|
||||
return jsonify({'imported': imported, 'skipped': skipped}), 200
|
||||
|
||||
Reference in New Issue
Block a user