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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# v153.0 (In progress)

### Autofill

- Added a new `passports` record type (name, country, passport number, issue/expiry dates) with full CRUD on the `Store` API. The schema is laid out sync-ready, but no sync engine is registered yet, so passports are not synced.

### Nimbus

- Enrollment change events (visible to the UDL) now include the feature IDs of the features involved when possible. ([#7391](https://github.com/mozilla/application-services/pull/7391/))
Expand Down
37 changes: 37 additions & 0 deletions components/autofill/sql/create_shared_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,43 @@ CREATE TABLE IF NOT EXISTS credit_cards_tombstones (
time_deleted INTEGER NOT NULL
) WITHOUT ROWID;

-- Passport records. The passport number is stored as plaintext (no field-level
-- encryption).
CREATE TABLE IF NOT EXISTS passports_data (
guid TEXT NOT NULL PRIMARY KEY CHECK(length(guid) != 0),
name TEXT NOT NULL, -- full name on passport
country TEXT NOT NULL, -- ISO 3166 code
passport_number TEXT NOT NULL,
issue_date_month INTEGER,
issue_date_day INTEGER,
issue_date_year INTEGER,
expiry_date_month INTEGER,
expiry_date_day INTEGER,
expiry_date_year INTEGER,

time_created INTEGER NOT NULL,
time_last_used INTEGER,
time_last_modified INTEGER NOT NULL,
times_used INTEGER NOT NULL,

/* Same "sync change counter" strategy used by other components. */
sync_change_counter INTEGER NOT NULL
);

-- What's on the server as the JSON payload.
CREATE TABLE IF NOT EXISTS passports_mirror (
guid TEXT NOT NULL PRIMARY KEY CHECK(length(guid) != 0),
-- The plain-text sync15 payload.
payload TEXT NOT NULL CHECK(length(payload) != 0)
);

-- Tombstones are items deleted locally but not deleted in the mirror (ie, ones
-- we are yet to upload)
CREATE TABLE IF NOT EXISTS passports_tombstones (
guid TEXT PRIMARY KEY CHECK(length(guid) != 0),
time_deleted INTEGER NOT NULL
) WITHOUT ROWID;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't have the shared triggers for this yet. That seems fine I guess until you sync though.


-- This table holds key-value metadata for the Autofill component and its consumers.
CREATE TABLE IF NOT EXISTS moz_meta (
key TEXT PRIMARY KEY,
Expand Down
13 changes: 13 additions & 0 deletions components/autofill/sql/create_sync_temp_tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,16 @@ CREATE TEMP TABLE credit_cards_sync_outgoing_staging (
payload TEXT NOT NULL CHECK(length(payload) != 0),
sync_change_counter INTEGER NOT NULL
);

DROP TABLE IF EXISTS passports_sync_staging;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because these are temp tables you don't actually need them yet - they can be added later without needing a migration. I guess there's no harm adding them though, but also no real benefit.

CREATE TEMP TABLE passports_sync_staging (
guid TEXT NOT NULL PRIMARY KEY CHECK(length(guid) != 0),
payload TEXT NOT NULL CHECK(length(payload) != 0)
);

DROP TABLE IF EXISTS passports_sync_outgoing_staging;
CREATE TEMP TABLE passports_sync_outgoing_staging (
guid TEXT NOT NULL PRIMARY KEY CHECK(length(guid) != 0),
payload TEXT NOT NULL CHECK(length(payload) != 0),
sync_change_counter INTEGER NOT NULL
);
36 changes: 36 additions & 0 deletions components/autofill/sql/migrations/v5_migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at http://mozilla.org/MPL/2.0/.

-- v4 -> v5: add the passports_data table and its sync mirror/tombstone tables.
CREATE TABLE IF NOT EXISTS passports_data (
guid TEXT NOT NULL PRIMARY KEY CHECK(length(guid) != 0),
name TEXT NOT NULL, -- full name on passport
country TEXT NOT NULL, -- ISO 3166 code
passport_number TEXT NOT NULL,
issue_date_month INTEGER,
issue_date_day INTEGER,
issue_date_year INTEGER,
expiry_date_month INTEGER,
expiry_date_day INTEGER,
expiry_date_year INTEGER,

time_created INTEGER NOT NULL,
time_last_used INTEGER,
time_last_modified INTEGER NOT NULL,
times_used INTEGER NOT NULL,

/* Same "sync change counter" strategy used by other components. */
sync_change_counter INTEGER NOT NULL
);

CREATE TABLE IF NOT EXISTS passports_mirror (
guid TEXT NOT NULL PRIMARY KEY CHECK(length(guid) != 0),
-- The plain-text sync15 payload.
payload TEXT NOT NULL CHECK(length(payload) != 0)
);

CREATE TABLE IF NOT EXISTS passports_tombstones (
guid TEXT PRIMARY KEY CHECK(length(guid) != 0),
time_deleted INTEGER NOT NULL
) WITHOUT ROWID;
105 changes: 105 additions & 0 deletions components/autofill/sql/tests/create_v4_db.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at http://mozilla.org/MPL/2.0/.

-- Initialize the v3 schema

CREATE TABLE IF NOT EXISTS addresses_data (
guid TEXT NOT NULL PRIMARY KEY CHECK(length(guid) != 0),
name TEXT NOT NULL,
organization TEXT NOT NULL, -- Company
street_address TEXT NOT NULL, -- (Multiline)
address_level3 TEXT NOT NULL, -- Suburb/Sublocality
address_level2 TEXT NOT NULL, -- City/Town
address_level1 TEXT NOT NULL, -- Province (Standardized code if possible)
postal_code TEXT NOT NULL,
country TEXT NOT NULL, -- ISO 3166
tel TEXT NOT NULL, -- Stored in E.164 format
email TEXT NOT NULL,

time_created INTEGER NOT NULL,
time_last_used INTEGER NOT NULL,
time_last_modified INTEGER NOT NULL,
times_used INTEGER NOT NULL,

sync_change_counter INTEGER NOT NULL
);

-- What's on the server as the JSON payload.
CREATE TABLE IF NOT EXISTS addresses_mirror (
guid TEXT NOT NULL PRIMARY KEY CHECK(length(guid) != 0),
payload TEXT NOT NULL CHECK(length(payload) != 0)
-- We could also have `modified`, which is in the server response and
-- passed around in the sync code, but we don't have a use-case for using it.
);

-- Tombstones are items deleted locally but not deleted in the mirror (ie, ones
-- we are yet to upload)
CREATE TABLE IF NOT EXISTS addresses_tombstones (
guid TEXT PRIMARY KEY CHECK(length(guid) != 0),
time_deleted INTEGER NOT NULL
) WITHOUT ROWID;

CREATE TABLE IF NOT EXISTS credit_cards_data (
guid TEXT NOT NULL PRIMARY KEY CHECK(length(guid) != 0),
cc_name TEXT NOT NULL,
cc_number_enc TEXT NOT NULL CHECK(length(cc_number_enc) > 20 OR cc_number_enc == ''),
cc_number_last_4 TEXT NOT NULL CHECK(length(cc_number_last_4) <= 4),
cc_exp_month INTEGER,
cc_exp_year INTEGER,
cc_type TEXT NOT NULL,
time_created INTEGER NOT NULL,
time_last_used INTEGER,
time_last_modified INTEGER NOT NULL,
times_used INTEGER NOT NULL,
sync_change_counter INTEGER NOT NULL
);

CREATE TABLE IF NOT EXISTS credit_cards_mirror (
guid TEXT NOT NULL PRIMARY KEY CHECK(length(guid) != 0),
payload TEXT NOT NULL CHECK(length(payload) != 0)
);

CREATE TABLE IF NOT EXISTS credit_cards_tombstones (
guid TEXT PRIMARY KEY CHECK(length(guid) != 0),
time_deleted INTEGER NOT NULL
) WITHOUT ROWID;

-- This table holds key-value metadata for the Autofill component and its consumers.
CREATE TABLE IF NOT EXISTS moz_meta (
key TEXT PRIMARY KEY,
value NOT NULL
) WITHOUT ROWID;

-- Populate it with some data, we test that this makes it through all the migrations.
INSERT INTO credit_cards_data (
guid, cc_name, cc_number_enc, cc_number_last_4, cc_exp_month, cc_exp_year,
cc_type, time_created, time_last_used, time_last_modified, times_used,
sync_change_counter
) VALUES (
"A", "Jane Doe", "012345678901234567890", "1234", 1, 2020, "visa", 0, 1, 2,
3, 0
);

INSERT INTO addresses_data (
guid, name, organization, street_address, address_level3,
address_level2, address_level1, postal_code, country, tel,
email, time_created, time_last_used, time_last_modified,
times_used, sync_change_counter
) VALUES (
"A", "Jane John Doe", "Mozilla", "123 Maple lane", "Shelbyville",
"Springfield", "Massachusetts", "12345", "US", "01-234-567-8000", "jane@hotmail.com", 0,
1, 2, 3, 0
);

INSERT INTO addresses_data (
guid, name, organization, street_address, address_level3,
address_level2, address_level1, postal_code, country, tel,
email, time_created, time_last_used, time_last_modified,
times_used, sync_change_counter
) VALUES (
"B", "", "Mozilla", "123 Maple lane", "Shelbyville",
"Toronto", "Ontario", "12345", "CA", "01-234-567-8000", "jane@hotmail.com", 0,
1, 2, 3, 0
);
PRAGMA user_version=4;
53 changes: 53 additions & 0 deletions components/autofill/src/autofill.udl
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,38 @@ dictionary Address {
i64 times_used;
};

/// What you pass to create or update a passport.
dictionary UpdatablePassportFields {
string name;
string country;
string passport_number;
i64 issue_date_month;
i64 issue_date_day;
i64 issue_date_year;
i64 expiry_date_month;
i64 expiry_date_day;
i64 expiry_date_year;
};

/// What you get back as a passport.
dictionary Passport {
string guid;
string name;
string country;
string passport_number;
i64 issue_date_month;
i64 issue_date_day;
i64 issue_date_year;
i64 expiry_date_month;
i64 expiry_date_day;
i64 expiry_date_year;

i64 time_created;
i64? time_last_used;
i64 time_last_modified;
i64 times_used;
};

/// Metrics tracking scrubbing of credit cards that cannot be decrypted, see
// `scrub_undecryptable_credit_card_data_for_remote_replacement` for more details
dictionary CreditCardsDeletionMetrics {
Expand Down Expand Up @@ -136,6 +168,27 @@ interface Store {
[Throws=AutofillApiError]
void touch_address(string guid);

[Throws=AutofillApiError]
Passport add_passport(UpdatablePassportFields p);

[Throws=AutofillApiError]
Passport get_passport(string guid);

[Throws=AutofillApiError]
sequence<Passport> get_all_passports();

[Throws=AutofillApiError]
i64 count_all_passports();

[Throws=AutofillApiError]
void update_passport(string guid, UpdatablePassportFields p);

[Throws=AutofillApiError]
boolean delete_passport(string guid);

[Throws=AutofillApiError]
void touch_passport(string guid);

[Throws=AutofillApiError, Self=ByArc]
void scrub_encrypted_data();

Expand Down
1 change: 1 addition & 0 deletions components/autofill/src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
pub mod addresses;
pub mod credit_cards;
pub mod models;
pub mod passports;
pub mod schema;
pub mod store;

Expand Down
1 change: 1 addition & 0 deletions components/autofill/src/db/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

pub mod address;
pub mod credit_card;
pub mod passport;
use types::Timestamp;

/// Metadata that's common between the records.
Expand Down
Loading