grownxt-server / scripts /verify_gdrive.py
StavanShah01's picture
refactor!: hosted-model-only core, Drive report delivery, shared harnesses
79cf149
Raw History Blame Contribute Delete
17.8 kB
"""Verification harness for the Google Drive delivery path.
Every check runs against an in-memory stand-in for Drive, so the whole upload,
sharing, token-refresh and caching path is verified with no credentials, no
network, and nothing uploaded to a real account:
venv/Scripts/python.exe -m scripts.verify_gdrive
The invariants here are the ones that would otherwise fail quietly in
production -- a second copy of every report accumulating in Drive, a report
uploaded but never shared, a link that stops resolving after a rebuild, or a
revoked grant reported as a transient error and retried forever.
"""
import json
import logging
import os
from pathlib import Path
import sys
import tempfile
import time
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from scripts import cli # noqa: E402
from scripts.checks import Report, banner # noqa: E402
import core.config as config # noqa: E402
import storage.gdrive as gdrive # noqa: E402
from storage.gdrive import ( # noqa: E402
API_BASE,
TOKEN_URL,
UPLOAD_BASE,
DriveAuthError,
DriveError,
DriveStore,
ensure_uploaded,
)
PDF_BYTES = b"%PDF-1.7\n" + b"x" * 512 + b"\n%%EOF\n"
class FakeResponse:
"""Minimal stand-in for a ``requests`` response."""
def __init__(self, status_code=200, payload=None, text=""):
self.status_code = status_code
self._payload = payload
self.text = text or (json.dumps(payload) if payload is not None else "")
def json(self):
if self._payload is None:
raise ValueError("no JSON body")
return self._payload
class FakeDrive:
"""An in-memory Drive: files with names, bytes, parents and permissions."""
def __init__(self, token_responses=None):
self.files = {}
self.permissions = {}
self.calls = []
self.next_id = 1
self.token_responses = list(token_responses or [])
self.token_calls = 0
# -- transport ---------------------------------------------------------
def post(self, url, data=None, json=None, timeout=None, headers=None):
"""Handles the token endpoint; everything else goes through request()."""
if url == TOKEN_URL:
self.token_calls += 1
if self.token_responses:
return self.token_responses.pop(0)
return FakeResponse(200, {"access_token": "at-%d" % self.token_calls, "expires_in": 3600})
return self.request("POST", url, data=data, json=json, headers=headers)
def request(self, method, url, headers=None, params=None, data=None, json=None, timeout=None):
params = params or {}
self.calls.append((method, url, params, headers or {}))
if method == "GET" and url == "%s/files" % API_BASE:
return self._list(params.get("q", ""))
if method == "POST" and url == "%s/files" % UPLOAD_BASE:
return self._create(data)
if method == "PATCH" and url.startswith("%s/files/" % UPLOAD_BASE):
return self._update(url.rsplit("/", 1)[-1], data)
if url.endswith("/permissions"):
file_id = url.rsplit("/", 2)[-2]
if method == "GET":
return FakeResponse(200, {"permissions": self.permissions.get(file_id, [])})
if method == "POST":
grant = dict(json or {})
grant["id"] = "perm-%d" % (len(self.permissions.get(file_id, [])) + 1)
self.permissions.setdefault(file_id, []).append(grant)
return FakeResponse(200, {"id": grant["id"]})
return FakeResponse(404, {"error": {"message": "unrouted %s %s" % (method, url)}})
# -- behaviour ---------------------------------------------------------
def _list(self, query):
name = None
if "name = '" in query:
name = query.split("name = '", 1)[1].split("'", 1)[0]
parent = None
if " in parents" in query:
parent = query.split("'", 1)[1].split("'", 1)[0] if query.startswith("'") else None
for part in query.split(" and "):
if part.endswith(" in parents"):
parent = part.split("'")[1]
matches = [
{"id": fid, "name": meta["name"]}
for fid, meta in self.files.items()
if meta["name"] == name and (parent is None or parent in meta.get("parents", []))
]
return FakeResponse(200, {"files": matches})
def _create(self, body):
metadata = {}
if body:
text = body.decode("utf-8", "replace")
start = text.find("{")
end = text.find("}", start)
if start >= 0 and end > start:
metadata = json.loads(text[start:end + 1])
file_id = "file-%d" % self.next_id
self.next_id += 1
self.files[file_id] = {
"name": metadata.get("name", "unnamed"),
"parents": metadata.get("parents", []),
"bytes": body or b"",
}
return FakeResponse(200, {
"id": file_id,
"name": self.files[file_id]["name"],
"webViewLink": "https://drive.google.com/file/d/%s/view" % file_id,
})
def _update(self, file_id, body):
if file_id not in self.files:
return FakeResponse(404, {"error": {"message": "no such file"}})
self.files[file_id]["bytes"] = body or b""
self.files[file_id]["updates"] = self.files[file_id].get("updates", 0) + 1
return FakeResponse(200, {
"id": file_id,
"name": self.files[file_id]["name"],
"webViewLink": "https://drive.google.com/file/d/%s/view" % file_id,
})
def _store(fake, **kwargs):
"""Builds a store wired to a fake Drive."""
options = {
"client_id": "cid",
"client_secret": "secret",
"refresh_token": "rt-original",
"folder_id": "",
"session": fake,
}
options.update(kwargs)
return DriveStore(**options)
def _write_pdf(directory: Path, body: bytes = PDF_BYTES) -> Path:
"""Writes a PDF into a directory and returns its path."""
directory.mkdir(parents=True, exist_ok=True)
path = directory / "WIPRO_report.pdf"
path.write_bytes(body)
return path
def check_configuration(r: Report) -> None:
"""Configuration and credential handling."""
saved = {k: os.environ.pop(k, None) for k in
("GDRIVE_CLIENT_ID", "GDRIVE_CLIENT_SECRET", "GDRIVE_REFRESH_TOKEN", "GDRIVE_TOKEN_FILE")}
try:
with tempfile.TemporaryDirectory() as tmp:
os.environ["GDRIVE_TOKEN_FILE"] = str(Path(tmp) / "token.json")
r.check("config.not_configured_reports_false", not gdrive.credentials_present(),
"no credentials present")
r.raises("config.missing_credentials_raise_auth_error", DriveAuthError,
lambda: DriveStore(client_id="", client_secret="", refresh_token=""))
os.environ["GDRIVE_CLIENT_ID"] = "cid"
os.environ["GDRIVE_CLIENT_SECRET"] = "secret"
os.environ["GDRIVE_REFRESH_TOKEN"] = "rt"
r.check("config.env_credentials_detected", gdrive.credentials_present(),
"client id, secret and refresh token seen")
os.environ.pop("GDRIVE_REFRESH_TOKEN")
path = gdrive.save_refresh_token("rt-from-file")
r.check("config.token_file_is_read_back",
gdrive.credentials_present() and gdrive._stored_token() == "rt-from-file",
"token file %s supplies the grant" % Path(path).name)
store = _store(FakeDrive(), refresh_token=None)
r.check("config.token_file_beats_env", store.refresh_token == "rt-from-file",
"the persisted token is preferred over the environment")
finally:
for key, value in saved.items():
if value is None:
os.environ.pop(key, None)
else:
os.environ[key] = value
def check_tokens(r: Report) -> None:
"""Access-token lifecycle: the part that keeps a long-running server alive."""
fake = FakeDrive()
store = _store(fake)
first = store.access_token()
second = store.access_token()
r.check("token.access_token_is_cached", first == second and fake.token_calls == 1,
"two calls, one refresh (%s)" % first)
store._expires_at = time.time() - 1
third = store.access_token()
r.check("token.expiry_triggers_refresh", third != first and fake.token_calls == 2,
"expired token replaced without intervention")
fake = FakeDrive(token_responses=[
FakeResponse(400, {"error": "invalid_grant",
"error_description": "Token has been expired or revoked."}),
])
store = _store(fake)
r.raises("token.invalid_grant_is_terminal", DriveAuthError, store.access_token,
"revoked grant surfaces as DriveAuthError")
# A fresh store, because the rejection above consumed the queued response.
store = _store(FakeDrive(token_responses=[
FakeResponse(400, {"error": "invalid_grant",
"error_description": "Token has been expired or revoked."}),
]))
message = ""
try:
store.access_token()
except DriveAuthError as exc:
message = str(exc)
r.check("token.invalid_grant_says_how_to_fix",
"scripts.gdrive_auth" in message and "Testing status" in message,
"names the re-auth command and the 7-day cause")
fake = FakeDrive(token_responses=[FakeResponse(503, {}, text="backend error")])
store = _store(fake)
r.raises("token.transient_failure_is_not_auth_error", DriveError, store.access_token,
"a 503 is retryable, not a lost grant")
fake = FakeDrive(token_responses=[FakeResponse(503, {}, text="backend error")])
store = _store(fake)
try:
store.access_token()
except DriveAuthError:
r.check("token.transient_failure_not_misreported", False, "503 raised DriveAuthError")
except DriveError:
r.check("token.transient_failure_not_misreported", True,
"DriveError, so the caller may retry")
saved = os.environ.get("GDRIVE_TOKEN_FILE")
with tempfile.TemporaryDirectory() as tmp:
token_file = Path(tmp) / "token.json"
os.environ["GDRIVE_TOKEN_FILE"] = str(token_file)
try:
fake = FakeDrive(token_responses=[FakeResponse(200, {
"access_token": "at-rotated", "expires_in": 3600, "refresh_token": "rt-rotated"})])
store = _store(fake)
store.access_token()
persisted = json.loads(token_file.read_text(encoding="utf-8")).get("refresh_token")
r.check("token.rotated_refresh_token_persisted",
store.refresh_token == "rt-rotated" and persisted == "rt-rotated",
"a rotated grant survives a restart")
finally:
if saved is None:
os.environ.pop("GDRIVE_TOKEN_FILE", None)
else:
os.environ["GDRIVE_TOKEN_FILE"] = saved
# A 401 mid-session: one silent retry, no error surfaced to the caller.
fake = FakeDrive()
calls = {"n": 0}
original = fake.request
def flaky(method, url, **kwargs):
calls["n"] += 1
if calls["n"] == 1:
return FakeResponse(401, {"error": {"message": "Invalid Credentials"}})
return original(method, url, **kwargs)
fake.request = flaky
store = _store(fake)
store.find_by_name("WIPRO_report.pdf")
r.check("token.401_retried_once_with_a_fresh_token",
calls["n"] == 2 and fake.token_calls == 2,
"one retry after re-minting the access token")
def check_upload(r: Report) -> None:
"""Upload, replacement and sharing."""
with tempfile.TemporaryDirectory() as tmp:
pdf = _write_pdf(Path(tmp))
fake = FakeDrive()
store = _store(fake)
first = store.upload(pdf)
r.check("upload.creates_when_absent", len(fake.files) == 1 and first.file_id in fake.files,
"one file created (%s)" % first.file_id)
body = fake.files[first.file_id]["bytes"]
r.check("upload.multipart_carries_metadata_and_pdf",
b"WIPRO_report.pdf" in body and b"%PDF-1.7" in body,
"%d bytes, metadata part and PDF part present" % len(body))
second = store.upload(pdf)
r.check("upload.replaces_rather_than_duplicating",
len(fake.files) == 1 and second.file_id == first.file_id,
"second upload reused %s" % second.file_id)
r.check("upload.replacement_is_a_media_patch",
fake.files[first.file_id].get("updates") == 1,
"existing file updated in place, so the link still resolves")
r.check("share.link_sharing_is_the_default",
any(p.get("type") == "anyone" and p.get("role") == "reader"
for p in fake.permissions.get(first.file_id, [])),
"anyone-with-link reader granted on upload")
r.check("share.existing_grant_is_not_recreated",
len(fake.permissions.get(first.file_id, [])) == 1,
"one permission after two uploads")
unshared = _store(FakeDrive())
result = unshared.upload(pdf, share=False)
r.check("share.can_be_declined_explicitly", result.shared is False,
"share=False leaves the file private")
r.check("links.preview_link_is_embeddable",
first.preview_link == "https://drive.google.com/file/d/%s/preview" % first.file_id,
first.preview_link)
r.check("links.direct_link_points_at_the_file",
first.file_id in first.direct_link and "export=download" in first.direct_link,
first.direct_link)
fake = FakeDrive()
store = _store(fake, folder_id="folder-123")
placed = store.upload(pdf)
r.check("upload.folder_id_is_applied",
fake.files[placed.file_id]["parents"] == ["folder-123"],
"file parented to the configured folder")
fake = FakeDrive()
store = _store(fake)
store.find_by_name("O'Brien & Sons_report.pdf")
query = [c for c in fake.calls if c[0] == "GET"][0][2].get("q", "")
r.check("upload.name_query_escapes_quotes", "O\\'Brien" in query,
"an apostrophe cannot break the query")
missing = _store(FakeDrive())
r.raises("upload.missing_file_is_refused", DriveError,
lambda: missing.upload(Path(tmp) / "nope.pdf"))
def check_caching(r: Report) -> None:
"""The sidecar: what stops every request re-uploading the same report."""
original_output = config.OUTPUT_DIR
with tempfile.TemporaryDirectory() as tmp:
config.OUTPUT_DIR = Path(tmp)
try:
ticker = "WIPRO"
pdf = _write_pdf(config.stock_dir(ticker))
fake = FakeDrive()
store = _store(fake)
first = ensure_uploaded(pdf, ticker, store=store)
sidecar = gdrive.sidecar_path(ticker)
record = json.loads(sidecar.read_text(encoding="utf-8"))
r.check("cache.sidecar_written", sidecar.exists() and record.get("file_id") == first.file_id,
"%s records the file id and links" % sidecar.name)
r.check("cache.sidecar_records_content_hash", len(record.get("pdf_sha256", "")) == 64,
"identity is the PDF's own hash")
uploads_before = len(fake.calls)
again = ensure_uploaded(pdf, ticker, store=store)
r.check("cache.unchanged_pdf_is_not_reuploaded",
len(fake.calls) == uploads_before and again.file_id == first.file_id,
"no Drive calls for an unchanged report")
pdf.write_bytes(PDF_BYTES + b"revised\n")
changed = ensure_uploaded(pdf, ticker, store=store)
r.check("cache.changed_pdf_is_reuploaded",
changed.file_id == first.file_id and fake.files[first.file_id].get("updates") == 1,
"same file id, new bytes -- the shared link is stable")
new_record = json.loads(sidecar.read_text(encoding="utf-8"))
r.check("cache.hash_advances_with_the_rebuild",
new_record["pdf_sha256"] != record["pdf_sha256"],
"sidecar tracks the new content")
forced_before = fake.files[first.file_id].get("updates")
ensure_uploaded(pdf, ticker, store=store, force=True)
r.check("cache.force_reuploads_identical_bytes",
fake.files[first.file_id].get("updates") == forced_before + 1,
"force=True bypasses the hash check")
gdrive.sidecar_path(ticker).write_text("{ not json", encoding="utf-8")
recovered = ensure_uploaded(pdf, ticker, store=store)
r.check("cache.corrupt_sidecar_is_survivable", bool(recovered.file_id),
"an unreadable sidecar re-uploads instead of crashing")
finally:
config.OUTPUT_DIR = original_output
def main() -> int:
"""Runs every check and returns a process exit code."""
cli.setup(logging.CRITICAL)
banner("Google Drive delivery verification (offline)")
report = Report()
for title, group in (("Configuration", check_configuration),
("Token handling", check_tokens),
("Upload and sharing", check_upload),
("Upload caching", check_caching)):
report.section(title)
group(report)
print(report.render())
return report.finish()
if __name__ == "__main__":
sys.exit(main())