Google's "Transfer accounts -> Export accounts" produces an otpauth-migration:// link wrapping a base64 protobuf that holds many accounts at once, and splits large exports across several QR codes. v0.1 rejected these outright; now they import. The protobuf is decoded by hand rather than pulling prost: the schema is four messages that have not changed since 2020, and the wire format needed is two types (varint, length-delimited). Unknown fields are skipped properly, so a future Google addition degrades rather than corrupting the parse. Two details in this format silently produce plausible-but-wrong codes if taken backwards, so both are pinned by tests: the `secret` field is RAW BYTES, not base32, and the payload carries NO period field -- every Google export is 30-second TOTP. - core/migration.rs: protobuf decode, lenient base64 (all four alphabet and padding spellings), issuer reconciliation between the `name` prefix and the dedicated `issuer` field, and batch metadata surfaced as "Part 1 of 2" - vault: add_many() with duplicate detection, persisting once per batch rather than once per account; duplicates match on secret AND naming, so keeping one secret under two labels stays possible - http-api: preview returns a list flagged with what is already stored; import takes the link plus selected indices and re-parses server-side, so secrets never travel out to the browser and back. /api/qr/decode now returns every payload in an image, not just the first - webui: multi-account import checklist with select all/none, per-entry algorithm and digit chips, already-present entries pre-unticked, and skipped entries named with their reason (HOTP, MD5) instead of silently dropped Verified end to end against real QR images: upload -> decode -> preview -> import, with the resulting codes cross-checked against an independent RFC 6238 implementation, including an 8-digit account. 124 tests (was 101). Co-Authored-By: Claude Opus 4.8 <[email protected]>
33 lines
774 B
TOML
33 lines
774 B
TOML
[package]
|
|
name = "da-http-api"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
authors.workspace = true
|
|
description = "HTTP API and asset serving for Discord Authenticator."
|
|
|
|
[dependencies]
|
|
da-core.workspace = true
|
|
da-discord.workspace = true
|
|
da-render.workspace = true
|
|
da-webui.workspace = true
|
|
axum.workspace = true
|
|
tower-http.workspace = true
|
|
tokio.workspace = true
|
|
serde.workspace = true
|
|
serde_json.workspace = true
|
|
tracing.workspace = true
|
|
uuid.workspace = true
|
|
parking_lot.workspace = true
|
|
image.workspace = true
|
|
rqrr.workspace = true
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[dev-dependencies]
|
|
qrcode = { version = "0.14", default-features = false, features = ["image"] }
|
|
base64.workspace = true
|