Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
618 changes: 618 additions & 0 deletions examples/sdk_examples/one_time_share/create_ots.py

Large diffs are not rendered by default.

77 changes: 43 additions & 34 deletions examples/sdk_examples/one_time_share/list_shares.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import sqlite3
import json
import logging
from datetime import datetime

from typing import Dict, Optional

import fido2
Expand All @@ -20,7 +20,7 @@
yubikey_authenticate,
)
from keepersdk.constants import KEEPER_PUBLIC_HOSTS
from keepersdk.vault import sqlite_storage, vault_online, ksm_management
from keepersdk.vault import one_time_share, sqlite_storage, vault_online
from keepersdk import utils

try:
Expand Down Expand Up @@ -497,51 +497,60 @@ def login():
return keeper_auth_context, keeper_endpoint


def list_one_time_shares(keeper_auth_context: keeper_auth.KeeperAuth):
conn = sqlite3.Connection('file::memory:', uri=True)
vault_storage = sqlite_storage.SqliteVaultStorage(lambda: conn, vault_owner=bytes(keeper_auth_context.auth_context.username, 'utf-8'))
def list_one_time_shares(keeper_auth_context: keeper_auth.KeeperAuth) -> None:
conn = sqlite3.Connection("file::memory:", uri=True)
vault_storage = sqlite_storage.SqliteVaultStorage(
lambda: conn,
vault_owner=bytes(keeper_auth_context.auth_context.username, "utf-8"),
)
vault = vault_online.VaultOnline(keeper_auth_context, vault_storage)
vault.sync_down()
try:
record_search = input('Enter record name/UID to check for shares (or leave empty for all records): ').strip()
record_search = input(
"Enter record name/UID to check for shares (or leave empty for all records): "
).strip()
record_uids = []
for record_info in vault.vault_data.records():
if record_info.version not in (2, 3):
continue
if not record_search or record_search.lower() in record_info.title.lower() or record_search == record_info.record_uid:
if (
not record_search
or record_search.lower() in record_info.title.lower()
or record_search == record_info.record_uid
):
record_uids.append(record_info.record_uid)
if not record_uids:
print("\nNo records found to check for one-time shares")
else:
app_infos = ksm_management.get_app_info(vault=vault, app_uid=record_uids[:100])
shares_found = []
now = utils.current_milli_time()
for app_info in app_infos:
if not app_info.isExternalShare:
continue
record_uid = utils.base64_url_encode(app_info.appRecordUid)
record_info = vault.vault_data.get_record(record_uid)
record_title = record_info.title if record_info else 'Unknown'
for client in app_info.clients:
shares_found.append({
'record_title': record_title,
'share_name': client.id if client.id else 'Unnamed',
'created': datetime.fromtimestamp(client.createdOn / 1000) if client.createdOn else None,
'expires': datetime.fromtimestamp(client.accessExpireOn / 1000) if client.accessExpireOn else None,
'expired': now > client.accessExpireOn if client.accessExpireOn else False,
'opened': datetime.fromtimestamp(client.firstAccess / 1000) if client.firstAccess else None
})
if not shares_found:
shares: list[one_time_share.OneTimeShare] = one_time_share.list_one_time_shares(
vault=vault,
record_uid=record_uids[:1000],
include_expired=True,
)
if not shares:
print("\nNo one-time shares found")
else:
print(f"\nOne-Time Shares ({len(shares_found)})\n{'=' * 130}")
print(f"{'Record Title':<30} {'Share Name':<20} {'Created':<20} {'Expires':<20} {'Status':<15}\n{'-' * 130}")
for share in shares_found:
status = 'Expired' if share['expired'] else ('Opened' if share['opened'] else 'Active')
created = share['created'].strftime('%Y-%m-%d %H:%M') if share['created'] else 'N/A'
expires = share['expires'].strftime('%Y-%m-%d %H:%M') if share['expires'] else 'N/A'
print(f"{share['record_title'][:29]:<30} {share['share_name'][:19]:<20} {created:<20} {expires:<20} {status:<15}")
print(f"{'-' * 130}\nTotal: {len(shares_found)}")
print(f"\nOne-Time Shares ({len(shares)})\n{'=' * 130}")
print(
f"{'Record Title':<30} {'Share Name':<20} {'Created':<20} {'Expires':<20} {'Status':<15}\n{'-' * 130}"
)
for share in shares:
record_info = vault.vault_data.get_record(share.record_uid)
record_title = record_info.title if record_info else "Unknown"
created = (
share.generated.strftime("%Y-%m-%d %H:%M")
if share.generated
else "N/A"
)
expires = (
share.expires.strftime("%Y-%m-%d %H:%M")
if share.expires
else "N/A"
)
print(
f"{record_title[:29]:<30} {share.share_link_name[:19]:<20} {created:<20} {expires:<20} {share.status:<15}"
)
print(f"{'-' * 130}\nTotal: {len(shares)}")
print("=" * 130)
except Exception as e:
print(f"Error retrieving one-time shares: {e}")
Expand Down
Loading