Skip to content

Commit 44fb70d

Browse files
committed
Add identities table and sync cron
1 parent 89e2ccc commit 44fb70d

5 files changed

Lines changed: 425 additions & 4 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
-- Global identity directory: one row per person, indexed by DID.
2+
-- DID is nullable for email-only records that haven't been linked yet.
3+
4+
CREATE TABLE IF NOT EXISTS identities (
5+
id SERIAL PRIMARY KEY,
6+
did TEXT UNIQUE,
7+
email TEXT,
8+
alt_email_1 TEXT,
9+
alt_email_2 TEXT,
10+
handle TEXT,
11+
display_name TEXT,
12+
avatar_url TEXT,
13+
is_member BOOLEAN DEFAULT FALSE,
14+
is_funder BOOLEAN DEFAULT FALSE,
15+
is_team BOOLEAN DEFAULT FALSE,
16+
is_oss_supporter BOOLEAN DEFAULT FALSE,
17+
source TEXT,
18+
member_updated_at BIGINT,
19+
funder_updated_at BIGINT,
20+
team_updated_at BIGINT,
21+
oss_updated_at BIGINT,
22+
created BIGINT DEFAULT now_as_millis(),
23+
modified BIGINT DEFAULT now_as_millis()
24+
);
25+
26+
CREATE INDEX IF NOT EXISTS identities_email_idx ON identities (LOWER(email));
27+
CREATE INDEX IF NOT EXISTS identities_alt_email_1_idx ON identities (LOWER(alt_email_1));
28+
CREATE INDEX IF NOT EXISTS identities_alt_email_2_idx ON identities (LOWER(alt_email_2));
29+
CREATE INDEX IF NOT EXISTS identities_handle_idx ON identities (LOWER(handle));

server/src/auth/atproto-admin.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ import pg from "../db/pg-query";
99

1010
// eslint-disable-next-line no-restricted-properties
1111
const FEEDGEN_DATABASE_URL = process.env.FEEDGEN_DATABASE_URL || "";
12+
// eslint-disable-next-line no-restricted-properties
13+
const FEEDGEN_MEMBER_LIST = process.env.FEEDGEN_MEMBER_LIST || "blacksky";
1214
let feedgenPool: pgLib.Pool | null = null;
1315

14-
function getFeedgenPool(): pgLib.Pool {
16+
export function getFeedgenPool(): pgLib.Pool {
1517
if (!feedgenPool) {
1618
// Strip sslmode from URL — we configure SSL via the pool options
1719
const connStr = FEEDGEN_DATABASE_URL.replace(/[?&]sslmode=[^&]*/g, '');
@@ -24,6 +26,10 @@ function getFeedgenPool(): pgLib.Pool {
2426
return feedgenPool;
2527
}
2628

29+
export function isFeedgenConfigured(): boolean {
30+
return !!FEEDGEN_DATABASE_URL;
31+
}
32+
2733
const JWT_ALGORITHM = "RS256" as const;
2834
const JWT_EXPIRATION_SECONDS = 30 * 24 * 60 * 60; // 30 days
2935

@@ -185,8 +191,8 @@ export async function checkMembershipBatch(
185191
try {
186192
const pool = getFeedgenPool();
187193
const result = await pool.query(
188-
"SELECT DISTINCT did FROM membership WHERE did = ANY($1) AND included = true AND list = 'blacksky'",
189-
[dids]
194+
"SELECT DISTINCT did FROM membership WHERE did = ANY($1) AND included = true AND list = $2",
195+
[dids, FEEDGEN_MEMBER_LIST]
190196
);
191197
return new Set(result.rows.map((r: any) => r.did));
192198
} catch (err) {
@@ -223,7 +229,7 @@ const OC_MEMBERS_QUERY = `
223229
}
224230
`;
225231

226-
async function fetchOcMembersByRole(
232+
export async function fetchOcMembersByRole(
227233
role: string,
228234
): Promise<Set<string>> {
229235
const emails = new Set<string>();

server/src/auth/github-supporters.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,19 @@ export function isOssSupporter(
288288
return false;
289289
}
290290

291+
/**
292+
* Get the raw cache data for use by the identity sync cron.
293+
* Returns null if cache isn't ready yet.
294+
*/
295+
export function getGithubSupporterData(): {
296+
dids: Set<string>;
297+
handles: Set<string>;
298+
emails: Set<string>;
299+
} | null {
300+
if (!cache.ready) return null;
301+
return { dids: cache.dids, handles: cache.handles, emails: cache.emails };
302+
}
303+
291304
/**
292305
* Ensure cache is populated. Call on server startup or first request.
293306
*/

0 commit comments

Comments
 (0)