@remit/drizzle-service 0.0.88 → 0.0.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import Database from "better-sqlite3";
|
|
4
|
+
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
5
|
+
import { AccountRepo } from "./repos/i4-account.js";
|
|
6
|
+
import { accountTable } from "./schema.js";
|
|
7
|
+
import {
|
|
8
|
+
applyMigration,
|
|
9
|
+
migrationJournal,
|
|
10
|
+
} from "./test-shipped-sqlite-schema.js";
|
|
11
|
+
|
|
12
|
+
const MIGRATION = "0032_account_granted_scopes";
|
|
13
|
+
|
|
14
|
+
const atPredecessor = (): Database.Database => {
|
|
15
|
+
const sqlite = new Database(":memory:");
|
|
16
|
+
for (const entry of migrationJournal()) {
|
|
17
|
+
if (entry.tag === MIGRATION) return sqlite;
|
|
18
|
+
applyMigration(sqlite, entry.tag);
|
|
19
|
+
}
|
|
20
|
+
throw new Error(`${MIGRATION} is not in the journal`);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const migrateOnward = (sqlite: Database.Database): void => {
|
|
24
|
+
const tags = migrationJournal().map((entry) => entry.tag);
|
|
25
|
+
for (const tag of tags.slice(tags.indexOf(MIGRATION))) {
|
|
26
|
+
applyMigration(sqlite, tag);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const insertAccount = (
|
|
31
|
+
sqlite: Database.Database,
|
|
32
|
+
accountId: string,
|
|
33
|
+
authType: string,
|
|
34
|
+
): void => {
|
|
35
|
+
sqlite
|
|
36
|
+
.prepare(
|
|
37
|
+
`INSERT INTO account (
|
|
38
|
+
account_id, account_config_id, username, email, auth_type,
|
|
39
|
+
imap_host, imap_port, imap_tls, imap_start_tls, smtp_port,
|
|
40
|
+
is_active, connection_state, created_at, updated_at
|
|
41
|
+
) VALUES (?, 'config', 'person', 'person@example.com', ?,
|
|
42
|
+
'outlook.office365.com', 993, 1, 0, 587, 1,
|
|
43
|
+
'not_authenticated', 0, 0)`,
|
|
44
|
+
)
|
|
45
|
+
.run(accountId, authType);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
describe("an account written before granted scopes were recorded", () => {
|
|
49
|
+
test("a Microsoft account holds the mail grant its consent always asked for", async () => {
|
|
50
|
+
const sqlite = atPredecessor();
|
|
51
|
+
insertAccount(sqlite, "microsoft", "oauthMicrosoft");
|
|
52
|
+
insertAccount(sqlite, "password", "password");
|
|
53
|
+
|
|
54
|
+
migrateOnward(sqlite);
|
|
55
|
+
|
|
56
|
+
const repo = new AccountRepo(
|
|
57
|
+
drizzle(sqlite, { schema: { accounts: accountTable } }) as never,
|
|
58
|
+
);
|
|
59
|
+
assert.deepEqual((await repo.get("microsoft")).grantedScopes, [
|
|
60
|
+
"https://outlook.office.com/IMAP.AccessAsUser.All",
|
|
61
|
+
"https://outlook.office.com/SMTP.Send",
|
|
62
|
+
]);
|
|
63
|
+
assert.deepEqual((await repo.get("password")).grantedScopes, []);
|
|
64
|
+
sqlite.close();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -21,6 +21,13 @@ const atPredecessor = (): Database.Database => {
|
|
|
21
21
|
throw new Error(`${MIGRATION} is not in the journal`);
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
const migrateOnward = (sqlite: Database.Database): void => {
|
|
25
|
+
const tags = migrationJournal().map((entry) => entry.tag);
|
|
26
|
+
for (const tag of tags.slice(tags.indexOf(MIGRATION))) {
|
|
27
|
+
applyMigration(sqlite, tag);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
24
31
|
describe("an account written before the service selection existed", () => {
|
|
25
32
|
test("comes out of the migration syncing mail only", async () => {
|
|
26
33
|
const sqlite = atPredecessor();
|
|
@@ -36,7 +43,7 @@ describe("an account written before the service selection existed", () => {
|
|
|
36
43
|
)
|
|
37
44
|
.run();
|
|
38
45
|
|
|
39
|
-
|
|
46
|
+
migrateOnward(sqlite);
|
|
40
47
|
|
|
41
48
|
const repo = new AccountRepo(
|
|
42
49
|
drizzle(sqlite, { schema: { accounts: accountTable } }) as never,
|
package/src/repos/i4-account.ts
CHANGED
|
@@ -40,6 +40,7 @@ export function rowToAccount(
|
|
|
40
40
|
email: row.email,
|
|
41
41
|
authType: row.authType as AccountItem["authType"],
|
|
42
42
|
syncedServices: row.syncedServices as AccountItem["syncedServices"],
|
|
43
|
+
grantedScopes: row.grantedScopes as AccountItem["grantedScopes"],
|
|
43
44
|
passwordHash: row.passwordHash ?? undefined,
|
|
44
45
|
oauthRefreshTokenHash: row.oauthRefreshTokenHash ?? undefined,
|
|
45
46
|
oauthTokenUpdatedAt: row.oauthTokenUpdatedAt ?? undefined,
|
|
@@ -83,6 +84,7 @@ export class AccountRepo implements IAccountRepository {
|
|
|
83
84
|
email: input.email,
|
|
84
85
|
authType: input.authType ?? "password",
|
|
85
86
|
syncedServices: input.syncedServices ?? [AccountService.Mail],
|
|
87
|
+
grantedScopes: input.grantedScopes ?? [],
|
|
86
88
|
passwordHash: input.passwordHash,
|
|
87
89
|
oauthRefreshTokenHash: input.oauthRefreshTokenHash,
|
|
88
90
|
oauthTokenUpdatedAt: input.oauthTokenUpdatedAt,
|
|
@@ -148,6 +150,8 @@ export class AccountRepo implements IAccountRepository {
|
|
|
148
150
|
if (input.authType !== undefined) updates.authType = input.authType;
|
|
149
151
|
if (input.syncedServices !== undefined)
|
|
150
152
|
updates.syncedServices = input.syncedServices;
|
|
153
|
+
if (input.grantedScopes !== undefined)
|
|
154
|
+
updates.grantedScopes = input.grantedScopes;
|
|
151
155
|
if (input.passwordHash !== undefined)
|
|
152
156
|
updates.passwordHash = input.passwordHash;
|
|
153
157
|
if (input.oauthRefreshTokenHash !== undefined)
|