@automagik/omni 2.260923.5 → 2.260923.6
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.
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
-- Slack OAuth identity uniqueness (#1235, follow-up to #1233).
|
|
2
|
+
--
|
|
3
|
+
-- The OAuth callback upserts one instance per Slack identity, but nothing in
|
|
4
|
+
-- the database enforced it: two callbacks for the same identity landing
|
|
5
|
+
-- together could both insert. These partial unique indexes make the identity
|
|
6
|
+
-- a constraint and give the upsert an ON CONFLICT target:
|
|
7
|
+
--
|
|
8
|
+
-- instances_slack_oauth_user_uq (slack_team_id, slack_user_id) for
|
|
9
|
+
-- user-mode OAuth rows
|
|
10
|
+
-- instances_slack_oauth_bot_uq (slack_team_id) for bot-mode OAuth rows
|
|
11
|
+
-- (NULL slack_user_id) — two bot installs
|
|
12
|
+
-- for one workspace are one identity
|
|
13
|
+
--
|
|
14
|
+
-- Only slack_connection_method = 'oauth' rows are covered: the
|
|
15
|
+
-- instance.connected listener also fills the identity columns of manual
|
|
16
|
+
-- pasted-token instances, which may legitimately repeat.
|
|
17
|
+
--
|
|
18
|
+
-- Duplicate-row policy: detect and refuse. A database that already holds two
|
|
19
|
+
-- OAuth rows for one identity cannot build the index, so the DO block below
|
|
20
|
+
-- fails the migration with the duplicate instance ids instead. Resolve by
|
|
21
|
+
-- deleting the extra instance(s), then restart; nothing is deduped
|
|
22
|
+
-- automatically because each row carries its own live tokens.
|
|
23
|
+
--
|
|
24
|
+
-- Hand-written following the 0043/0044/0052 precedent (additive, idempotent).
|
|
25
|
+
-- No explicit BEGIN/COMMIT — the boot migrator executes this file on a pooled
|
|
26
|
+
-- postgres-js connection, which rejects raw transaction control.
|
|
27
|
+
|
|
28
|
+
DO $$
|
|
29
|
+
DECLARE
|
|
30
|
+
duplicates text;
|
|
31
|
+
BEGIN
|
|
32
|
+
SELECT string_agg(
|
|
33
|
+
format('team %s %s: instances %s',
|
|
34
|
+
slack_team_id,
|
|
35
|
+
COALESCE('user ' || slack_user_id, '(bot)'),
|
|
36
|
+
ids),
|
|
37
|
+
'; ')
|
|
38
|
+
INTO duplicates
|
|
39
|
+
FROM (
|
|
40
|
+
SELECT slack_team_id, slack_user_id, string_agg(id::text, ', ' ORDER BY created_at) AS ids
|
|
41
|
+
FROM "instances"
|
|
42
|
+
WHERE slack_connection_method = 'oauth' AND slack_team_id IS NOT NULL
|
|
43
|
+
GROUP BY slack_team_id, slack_user_id
|
|
44
|
+
HAVING count(*) > 1
|
|
45
|
+
) d;
|
|
46
|
+
|
|
47
|
+
IF duplicates IS NOT NULL THEN
|
|
48
|
+
RAISE EXCEPTION 'Duplicate Slack OAuth instances for one identity (#1235): %. Delete the extra instance(s) and restart.', duplicates;
|
|
49
|
+
END IF;
|
|
50
|
+
END $$;
|
|
51
|
+
|
|
52
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "instances_slack_oauth_user_uq"
|
|
53
|
+
ON "instances" ("slack_team_id", "slack_user_id")
|
|
54
|
+
WHERE "slack_connection_method" = 'oauth' AND "slack_user_id" IS NOT NULL;
|
|
55
|
+
|
|
56
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "instances_slack_oauth_bot_uq"
|
|
57
|
+
ON "instances" ("slack_team_id")
|
|
58
|
+
WHERE "slack_connection_method" = 'oauth' AND "slack_user_id" IS NULL;
|
|
@@ -554,6 +554,13 @@
|
|
|
554
554
|
"when": 1787800000000,
|
|
555
555
|
"tag": "0078_instances_slack_oauth_identity",
|
|
556
556
|
"breakpoints": true
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
"idx": 79,
|
|
560
|
+
"version": "7",
|
|
561
|
+
"when": 1787900000000,
|
|
562
|
+
"tag": "0079_instances_slack_identity_unique",
|
|
563
|
+
"breakpoints": true
|
|
557
564
|
}
|
|
558
565
|
]
|
|
559
566
|
}
|
package/dist/index.js
CHANGED
|
@@ -82460,6 +82460,8 @@ var init_schema2 = __esm(() => {
|
|
|
82460
82460
|
agentIdIdx: index("instances_agent_id_idx").on(table3.agentId),
|
|
82461
82461
|
metaPhoneNumberIdx: index("instances_meta_phone_number_idx").on(table3.metaPhoneNumberId),
|
|
82462
82462
|
slackIdentityIdx: index("instances_slack_identity_idx").on(table3.slackTeamId, table3.slackUserId),
|
|
82463
|
+
slackOAuthUserUq: uniqueIndex("instances_slack_oauth_user_uq").on(table3.slackTeamId, table3.slackUserId).where(sql`${table3.slackConnectionMethod} = 'oauth' AND ${table3.slackUserId} IS NOT NULL`),
|
|
82464
|
+
slackOAuthBotUq: uniqueIndex("instances_slack_oauth_bot_uq").on(table3.slackTeamId).where(sql`${table3.slackConnectionMethod} = 'oauth' AND ${table3.slackUserId} IS NULL`),
|
|
82463
82465
|
chainModeCheck: check("instances_chain_mode_check", sql`${table3.chainMode} IN ('off', 'forward', 'bidirectional')`)
|
|
82464
82466
|
}));
|
|
82465
82467
|
whatsappTemplates = pgTable("whatsapp_templates", {
|
|
@@ -115984,7 +115986,7 @@ var require_client2 = __commonJS((exports) => {
|
|
|
115984
115986
|
|
|
115985
115987
|
// ../../node_modules/.bun/@sentry+node-core@10.52.0+2c50d7e904f6cfd7/node_modules/@sentry/node-core/build/cjs/sdk/esmLoader.js
|
|
115986
115988
|
var require_esmLoader = __commonJS((exports) => {
|
|
115987
|
-
var __filename = "/home/runner/work/omni/omni
|
|
115989
|
+
var __filename = "/home/runner/work/omni/omni/node_modules/.bun/@sentry+node-core@10.52.0+2c50d7e904f6cfd7/node_modules/@sentry/node-core/build/cjs/sdk/esmLoader.js";
|
|
115988
115990
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
115989
115991
|
var core = require_cjs();
|
|
115990
115992
|
var importInTheMiddle = require_import_in_the_middle();
|
|
@@ -137460,7 +137462,7 @@ import { fileURLToPath } from "url";
|
|
|
137460
137462
|
// package.json
|
|
137461
137463
|
var package_default = {
|
|
137462
137464
|
name: "@automagik/omni",
|
|
137463
|
-
version: "2.260923.
|
|
137465
|
+
version: "2.260923.6",
|
|
137464
137466
|
repository: {
|
|
137465
137467
|
type: "git",
|
|
137466
137468
|
url: "git+https://github.com/automagik-dev/omni.git",
|
package/dist/server/index.js
CHANGED
|
@@ -77157,7 +77157,7 @@ var require_ClientVoiceManager = __commonJS((exports, module) => {
|
|
|
77157
77157
|
|
|
77158
77158
|
// ../../node_modules/.bun/@discordjs+ws@1.2.3/node_modules/@discordjs/ws/dist/index.js
|
|
77159
77159
|
var require_dist9 = __commonJS((exports, module) => {
|
|
77160
|
-
var __dirname = "/home/runner/work/omni/omni
|
|
77160
|
+
var __dirname = "/home/runner/work/omni/omni/node_modules/.bun/@discordjs+ws@1.2.3/node_modules/@discordjs/ws/dist";
|
|
77161
77161
|
var __create2 = Object.create;
|
|
77162
77162
|
var __defProp2 = Object.defineProperty;
|
|
77163
77163
|
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
@@ -176984,7 +176984,7 @@ var require_indexes = __commonJS((exports, module) => {
|
|
|
176984
176984
|
|
|
176985
176985
|
// ../../node_modules/.bun/thread-stream@3.1.0/node_modules/thread-stream/index.js
|
|
176986
176986
|
var require_thread_stream = __commonJS((exports, module) => {
|
|
176987
|
-
var __dirname = "/home/runner/work/omni/omni
|
|
176987
|
+
var __dirname = "/home/runner/work/omni/omni/node_modules/.bun/thread-stream@3.1.0/node_modules/thread-stream";
|
|
176988
176988
|
var { version } = require_package5();
|
|
176989
176989
|
var { EventEmitter: EventEmitter3 } = __require("events");
|
|
176990
176990
|
var { Worker } = __require("worker_threads");
|
|
@@ -177405,7 +177405,7 @@ var require_thread_stream = __commonJS((exports, module) => {
|
|
|
177405
177405
|
|
|
177406
177406
|
// ../../node_modules/.bun/pino@9.14.0/node_modules/pino/lib/transport.js
|
|
177407
177407
|
var require_transport2 = __commonJS((exports, module) => {
|
|
177408
|
-
var __dirname = "/home/runner/work/omni/omni
|
|
177408
|
+
var __dirname = "/home/runner/work/omni/omni/node_modules/.bun/pino@9.14.0/node_modules/pino/lib";
|
|
177409
177409
|
var { createRequire: createRequire2 } = __require("module");
|
|
177410
177410
|
var getCallers = require_caller();
|
|
177411
177411
|
var { join: join8, isAbsolute, sep: sep2 } = __require("path");
|
|
@@ -188261,6 +188261,8 @@ var init_schema2 = __esm(() => {
|
|
|
188261
188261
|
agentIdIdx: index("instances_agent_id_idx").on(table3.agentId),
|
|
188262
188262
|
metaPhoneNumberIdx: index("instances_meta_phone_number_idx").on(table3.metaPhoneNumberId),
|
|
188263
188263
|
slackIdentityIdx: index("instances_slack_identity_idx").on(table3.slackTeamId, table3.slackUserId),
|
|
188264
|
+
slackOAuthUserUq: uniqueIndex("instances_slack_oauth_user_uq").on(table3.slackTeamId, table3.slackUserId).where(sql`${table3.slackConnectionMethod} = 'oauth' AND ${table3.slackUserId} IS NOT NULL`),
|
|
188265
|
+
slackOAuthBotUq: uniqueIndex("instances_slack_oauth_bot_uq").on(table3.slackTeamId).where(sql`${table3.slackConnectionMethod} = 'oauth' AND ${table3.slackUserId} IS NULL`),
|
|
188264
188266
|
chainModeCheck: check("instances_chain_mode_check", sql`${table3.chainMode} IN ('off', 'forward', 'bidirectional')`)
|
|
188265
188267
|
}));
|
|
188266
188268
|
whatsappTemplates = pgTable("whatsapp_templates", {
|
|
@@ -259216,7 +259218,7 @@ var require_client3 = __commonJS((exports) => {
|
|
|
259216
259218
|
|
|
259217
259219
|
// ../../node_modules/.bun/@sentry+node-core@10.52.0+2c50d7e904f6cfd7/node_modules/@sentry/node-core/build/cjs/sdk/esmLoader.js
|
|
259218
259220
|
var require_esmLoader = __commonJS((exports) => {
|
|
259219
|
-
var __filename = "/home/runner/work/omni/omni
|
|
259221
|
+
var __filename = "/home/runner/work/omni/omni/node_modules/.bun/@sentry+node-core@10.52.0+2c50d7e904f6cfd7/node_modules/@sentry/node-core/build/cjs/sdk/esmLoader.js";
|
|
259220
259222
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
259221
259223
|
var core3 = require_cjs6();
|
|
259222
259224
|
var importInTheMiddle = require_import_in_the_middle();
|
|
@@ -266442,7 +266444,7 @@ var init_sentry_scrub = __esm(() => {
|
|
|
266442
266444
|
var require_package7 = __commonJS((exports, module) => {
|
|
266443
266445
|
module.exports = {
|
|
266444
266446
|
name: "@omni/api",
|
|
266445
|
-
version: "2.260923.
|
|
266447
|
+
version: "2.260923.6",
|
|
266446
266448
|
private: true,
|
|
266447
266449
|
type: "module",
|
|
266448
266450
|
exports: {
|
|
@@ -293545,7 +293547,7 @@ var require_src45 = __commonJS((exports) => {
|
|
|
293545
293547
|
|
|
293546
293548
|
// ../../node_modules/.bun/@grpc+grpc-js@1.14.3/node_modules/@grpc/grpc-js/build/src/channelz.js
|
|
293547
293549
|
var require_channelz = __commonJS((exports) => {
|
|
293548
|
-
var __dirname = "/home/runner/work/omni/omni
|
|
293550
|
+
var __dirname = "/home/runner/work/omni/omni/node_modules/.bun/@grpc+grpc-js@1.14.3/node_modules/@grpc/grpc-js/build/src";
|
|
293549
293551
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
293550
293552
|
exports.registerChannelzSocket = exports.registerChannelzServer = exports.registerChannelzSubchannel = exports.registerChannelzChannel = exports.ChannelzCallTrackerStub = exports.ChannelzCallTracker = exports.ChannelzChildrenTrackerStub = exports.ChannelzChildrenTracker = exports.ChannelzTrace = exports.ChannelzTraceStub = undefined;
|
|
293551
293553
|
exports.unregisterChannelzRef = unregisterChannelzRef;
|
|
@@ -298948,7 +298950,7 @@ var require_duration = __commonJS((exports) => {
|
|
|
298948
298950
|
|
|
298949
298951
|
// ../../node_modules/.bun/@grpc+grpc-js@1.14.3/node_modules/@grpc/grpc-js/build/src/orca.js
|
|
298950
298952
|
var require_orca = __commonJS((exports) => {
|
|
298951
|
-
var __dirname = "/home/runner/work/omni/omni
|
|
298953
|
+
var __dirname = "/home/runner/work/omni/omni/node_modules/.bun/@grpc+grpc-js@1.14.3/node_modules/@grpc/grpc-js/build/src";
|
|
298952
298954
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
298953
298955
|
exports.OrcaOobMetricsSubchannelWrapper = exports.GRPC_METRICS_HEADER = exports.ServerMetricRecorder = exports.PerRequestMetricRecorder = undefined;
|
|
298954
298956
|
exports.createOrcaClient = createOrcaClient;
|
|
@@ -387615,12 +387617,39 @@ class InstanceService {
|
|
|
387615
387617
|
const [row] = await this.db.select({ tenantId: instances.tenantId }).from(instances).where(eq(instances.id, id)).limit(1);
|
|
387616
387618
|
return this.sealTenantFor(row?.tenantId ?? null);
|
|
387617
387619
|
}
|
|
387620
|
+
async findBySlackIdentity(teamId, userId) {
|
|
387621
|
+
const [row] = await this.db.select().from(instances).where(and2(eq(instances.slackConnectionMethod, "oauth"), eq(instances.slackTeamId, teamId), userId === null ? isNull2(instances.slackUserId) : eq(instances.slackUserId, userId))).limit(1);
|
|
387622
|
+
if (!row)
|
|
387623
|
+
return;
|
|
387624
|
+
rememberInstanceOwners([row]);
|
|
387625
|
+
return openInstanceCredentials(row);
|
|
387626
|
+
}
|
|
387618
387627
|
async create(data) {
|
|
387619
|
-
const
|
|
387620
|
-
const [created] = await this.db.insert(instances).values(sealInstanceCredentials(this.sealTenantFor(rowTenant), data)).returning();
|
|
387628
|
+
const created = await this.insert(data, false);
|
|
387621
387629
|
if (!created) {
|
|
387622
387630
|
throw new Error("Failed to create instance");
|
|
387623
387631
|
}
|
|
387632
|
+
return created;
|
|
387633
|
+
}
|
|
387634
|
+
async createSlackOAuth(data) {
|
|
387635
|
+
return this.insert({ ...data, slackConnectionMethod: "oauth" }, true);
|
|
387636
|
+
}
|
|
387637
|
+
async insert(data, slackIdentityConflict) {
|
|
387638
|
+
const rowTenant = data.tenantId ?? null;
|
|
387639
|
+
const query = this.db.insert(instances).values(sealInstanceCredentials(this.sealTenantFor(rowTenant), data));
|
|
387640
|
+
if (slackIdentityConflict) {
|
|
387641
|
+
query.onConflictDoNothing(data.slackUserId == null ? {
|
|
387642
|
+
target: instances.slackTeamId,
|
|
387643
|
+
where: sql`${instances.slackConnectionMethod} = 'oauth' AND ${instances.slackUserId} IS NULL`
|
|
387644
|
+
} : {
|
|
387645
|
+
target: [instances.slackTeamId, instances.slackUserId],
|
|
387646
|
+
where: sql`${instances.slackConnectionMethod} = 'oauth' AND ${instances.slackUserId} IS NOT NULL`
|
|
387647
|
+
});
|
|
387648
|
+
}
|
|
387649
|
+
const [created] = await query.returning();
|
|
387650
|
+
if (!created) {
|
|
387651
|
+
return null;
|
|
387652
|
+
}
|
|
387624
387653
|
rememberInstanceOwners([created]);
|
|
387625
387654
|
if (this.eventBus) {
|
|
387626
387655
|
await this.eventBus.publish("instance.connected", {
|
|
@@ -412858,19 +412887,8 @@ function isAllowedReturnTo(returnTo, publicOrigin) {
|
|
|
412858
412887
|
}
|
|
412859
412888
|
return url.origin === publicOrigin && url.search === "" && url.hash === "";
|
|
412860
412889
|
}
|
|
412861
|
-
function
|
|
412862
|
-
|
|
412863
|
-
return false;
|
|
412864
|
-
if (input.mode === "user")
|
|
412865
|
-
return row.slackUserId === input.userId && row.slackAuthMode === "user";
|
|
412866
|
-
return row.slackUserId == null && (row.slackAuthMode ?? "bot") === "bot";
|
|
412867
|
-
}
|
|
412868
|
-
async function findExisting(instances2, input) {
|
|
412869
|
-
const page = await instances2.list({ channel: ["slack"], limit: SLACK_LOOKUP_LIMIT });
|
|
412870
|
-
if (page.hasMore) {
|
|
412871
|
-
log127.warn("Slack OAuth identity lookup truncated; add a service finder", { limit: SLACK_LOOKUP_LIMIT });
|
|
412872
|
-
}
|
|
412873
|
-
return page.items.find((row) => matchesIdentity(row, input));
|
|
412890
|
+
function findExisting(instances2, input) {
|
|
412891
|
+
return instances2.findBySlackIdentity(input.teamId, input.mode === "user" ? input.userId : null);
|
|
412874
412892
|
}
|
|
412875
412893
|
function baseName(input) {
|
|
412876
412894
|
const team = (input.teamName ?? input.teamId).trim() || input.teamId;
|
|
@@ -412903,7 +412921,7 @@ async function createWithUniqueName(instances2, input) {
|
|
|
412903
412921
|
for (let attempt = 1;attempt <= NAME_SUFFIX_ATTEMPTS; attempt++) {
|
|
412904
412922
|
const name = attempt === 1 ? base2 : `${base2} ${attempt}`;
|
|
412905
412923
|
try {
|
|
412906
|
-
return await instances2.
|
|
412924
|
+
return await instances2.createSlackOAuth({
|
|
412907
412925
|
name,
|
|
412908
412926
|
channel: "slack",
|
|
412909
412927
|
profileName: input.mode === "user" ? input.displayName ?? null : input.teamName ?? null,
|
|
@@ -412956,8 +412974,14 @@ function resolvePlugin(registry5) {
|
|
|
412956
412974
|
async function upsertSlackOAuthInstance(deps, input) {
|
|
412957
412975
|
const plugin13 = resolvePlugin(deps.channelRegistry);
|
|
412958
412976
|
const existing = await findExisting(deps.instances, input);
|
|
412959
|
-
|
|
412960
|
-
const created =
|
|
412977
|
+
let row = existing ? null : await createWithUniqueName(deps.instances, input);
|
|
412978
|
+
const created = row !== null;
|
|
412979
|
+
if (!row) {
|
|
412980
|
+
const current = existing ?? await findExisting(deps.instances, input);
|
|
412981
|
+
if (!current)
|
|
412982
|
+
throw new Error("slack-oauth: identity conflict but no row found");
|
|
412983
|
+
row = await deps.instances.update(current.id, credentialColumns(input));
|
|
412984
|
+
}
|
|
412961
412985
|
log127.info(created ? "Slack OAuth instance created" : "Slack OAuth instance re-authorized", {
|
|
412962
412986
|
instanceId: row.id,
|
|
412963
412987
|
teamId: input.teamId,
|
|
@@ -412972,7 +412996,7 @@ async function upsertSlackOAuthInstance(deps, input) {
|
|
|
412972
412996
|
}
|
|
412973
412997
|
return { instanceId: row.id, created };
|
|
412974
412998
|
}
|
|
412975
|
-
var log127,
|
|
412999
|
+
var log127, NAME_MAX = 200, NAME_SUFFIX_ATTEMPTS = 20;
|
|
412976
413000
|
var init_slack_oauth2 = __esm(() => {
|
|
412977
413001
|
init_src4();
|
|
412978
413002
|
init_src();
|