mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-19 05:55:34 +09:00
feat(threads): ship threads and the Plutonium page to everyone (#3277)
This commit is contained in:
1 parent
1515a8487f
commit
f8505d19f7
53 files changed
+296
-2008
No files matched your search
@@ -15,7 +15,7 @@ import type {IUserRepository} from '@app/api/user/IUserRepository';
|
||||
import {ChannelTypes} from '@fluxer/constants/src/ChannelConstants';
|
||||
import {UnknownChannelError} from '@fluxer/errors/src/domains/channel/UnknownChannelError';
|
||||
import {ChannelThreadsConfigSchema} from '@fluxer/schema/src/domains/admin/ChannelThreadsSchemas';
|
||||
import {afterEach, describe, expect, it} from 'vitest';
|
||||
import {beforeEach, describe, expect, it} from 'vitest';
|
||||
|
||||
const GUILD_ID = createGuildID(100n);
|
||||
const CHANNEL_ID = createChannelID(300n);
|
||||
@@ -54,7 +54,7 @@ function enroll(): void {
|
||||
const capableViewer: ThreadViewer = {kind: 'user', userId: USER_ID, bot: false, capable: true};
|
||||
|
||||
describe('getChannelAuthenticated thread gate', () => {
|
||||
afterEach(() => {
|
||||
beforeEach(() => {
|
||||
syncChannelThreadsConfig(null, () => ChannelThreadsConfigSchema.parse({}));
|
||||
});
|
||||
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
import {
|
||||
clearChannelThreadsTaintCacheForTesting,
|
||||
syncChannelThreadsConfig,
|
||||
getCompiledChannelThreadsConfig,
|
||||
pinChannelThreadsConfigForTesting,
|
||||
} from '@app/api/experiment/ChannelThreadsGate';
|
||||
import {getInstanceConfigRepository} from '@app/api/middleware/ServiceSingletons';
|
||||
import type {ApiTestHarness} from '@app/api/test/ApiTestHarness';
|
||||
import {createBuilder, type TestRequestBuilder} from '@app/api/test/TestRequestBuilder';
|
||||
import {
|
||||
type ChannelThreadsConfig,
|
||||
ChannelThreadsConfigSchema,
|
||||
DEFAULT_CHANNEL_THREADS_CONFIG,
|
||||
} from '@fluxer/schema/src/domains/admin/ChannelThreadsSchemas';
|
||||
|
||||
export const THREADS_FEATURE_HEADER = 'X-Fluxer-Features';
|
||||
@@ -22,7 +23,8 @@ export const ALL_THREADS_ACTIVE: Partial<ChannelThreadsConfig> = {
|
||||
};
|
||||
|
||||
export async function setChannelThreadsConfig(patch: Partial<ChannelThreadsConfig>): Promise<void> {
|
||||
await getInstanceConfigRepository().updateChannelThreadsConfig((current) =>
|
||||
const current = getCompiledChannelThreadsConfig().config;
|
||||
pinChannelThreadsConfigForTesting(
|
||||
ChannelThreadsConfigSchema.parse({
|
||||
...patch,
|
||||
ever_enabled: current.ever_enabled || patch.enabled === true,
|
||||
@@ -33,7 +35,7 @@ export async function setChannelThreadsConfig(patch: Partial<ChannelThreadsConfi
|
||||
}
|
||||
|
||||
export function resetChannelThreadsConfig(): void {
|
||||
syncChannelThreadsConfig(null, (raw) => ChannelThreadsConfigSchema.parse(raw ? JSON.parse(raw) : {}));
|
||||
pinChannelThreadsConfigForTesting(DEFAULT_CHANNEL_THREADS_CONFIG);
|
||||
clearChannelThreadsTaintCacheForTesting();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,14 +28,6 @@ export async function enqueueRemoveThreadMemberships(guildId: GuildID, userId: U
|
||||
);
|
||||
}
|
||||
|
||||
export async function enqueueRebuildThreadAutoArchiveQueue(guildId: string): Promise<void> {
|
||||
await (await workerService()).addJob(
|
||||
'rebuildThreadAutoArchiveQueue',
|
||||
{guildId, configVersion: getCompiledChannelThreadsConfig().config.config_version},
|
||||
{jobKey: `rebuild-thread-archive-queue-${guildId}`},
|
||||
);
|
||||
}
|
||||
|
||||
export function enqueueRepairThreadIndexes(threadIds: Array<ChannelID>): void {
|
||||
if (threadIds.length === 0) return;
|
||||
const window = Math.floor(Date.now() / REPAIR_DEBOUNCE_MS);
|
||||
|
||||
@@ -2,21 +2,14 @@
|
||||
|
||||
import {createTestAccount} from '@app/api/auth/tests/AuthTestUtils';
|
||||
import {createDmChannel, createFriendship, createGuild} from '@app/api/channel/tests/ChannelTestUtils';
|
||||
import {resetChannelThreadsConfig, setChannelThreadsConfig} from '@app/api/channel/tests/ThreadTestUtils';
|
||||
import {setCassandraQueryExecutorForTesting} from '@app/api/database/CassandraQueryExecution';
|
||||
import type {CassandraParams, KvQueryMeta, PreparedQuery} from '@app/api/database/CassandraTypes';
|
||||
import {
|
||||
clearChannelThreadsTaintCacheForTesting,
|
||||
syncChannelThreadsConfig,
|
||||
} from '@app/api/experiment/ChannelThreadsGate';
|
||||
import {getInstanceConfigRepository} from '@app/api/middleware/ServiceSingletons';
|
||||
import {getCompiledChannelThreadsConfig} from '@app/api/experiment/ChannelThreadsGate';
|
||||
import {type ApiTestHarness, createApiTestHarness} from '@app/api/test/ApiTestHarness';
|
||||
import {InMemoryCassandraQueryExecutor} from '@app/api/test/InMemoryCassandraQueryExecutor';
|
||||
import {HTTP_STATUS} from '@app/api/test/TestConstants';
|
||||
import {createBuilder} from '@app/api/test/TestRequestBuilder';
|
||||
import {
|
||||
applyChannelThreadsConfigUpdate,
|
||||
ChannelThreadsConfigSchema,
|
||||
} from '@fluxer/schema/src/domains/admin/ChannelThreadsSchemas';
|
||||
import {afterAll, afterEach, beforeAll, beforeEach, describe, expect, it} from 'vitest';
|
||||
|
||||
class RecordingExecutor extends InMemoryCassandraQueryExecutor {
|
||||
@@ -38,11 +31,6 @@ class RecordingExecutor extends InMemoryCassandraQueryExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
function resetConfig(): void {
|
||||
syncChannelThreadsConfig(null, (raw) => ChannelThreadsConfigSchema.parse(raw ? JSON.parse(raw) : {}));
|
||||
clearChannelThreadsTaintCacheForTesting();
|
||||
}
|
||||
|
||||
describe('channel threads control identity', () => {
|
||||
let harness: ApiTestHarness;
|
||||
let executor: RecordingExecutor;
|
||||
@@ -53,13 +41,13 @@ describe('channel threads control identity', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await harness.reset();
|
||||
resetConfig();
|
||||
resetChannelThreadsConfig();
|
||||
executor = new RecordingExecutor();
|
||||
setCassandraQueryExecutorForTesting(executor);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetConfig();
|
||||
resetChannelThreadsConfig();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
@@ -93,10 +81,8 @@ describe('channel threads control identity', () => {
|
||||
const baselineDm = await recorded(() => createDmChannel(harness, baseline.owner.token, baseline.friend.userId));
|
||||
const baselineChannels = await loadChannels(baselineGuild.result.id);
|
||||
|
||||
await getInstanceConfigRepository().updateChannelThreadsConfig((current) =>
|
||||
applyChannelThreadsConfigUpdate(current, {enabled: true, enabled_guild_ids: ['1']}),
|
||||
);
|
||||
expect((await getInstanceConfigRepository().refreshChannelThreadsConfig()).config.ever_enabled).toBe(true);
|
||||
await setChannelThreadsConfig({enabled: true, enabled_guild_ids: ['1']});
|
||||
expect(getCompiledChannelThreadsConfig().config.ever_enabled).toBe(true);
|
||||
|
||||
const enrolledOff = await createPair();
|
||||
const guild = await recorded(() => createGuild(harness, enrolledOff.owner.token, 'control'));
|
||||
|
||||
@@ -3,22 +3,20 @@
|
||||
import {createTestAccount, type TestAccount} from '@app/api/auth/tests/AuthTestUtils';
|
||||
import {createTestBotAccount} from '@app/api/bot/tests/BotTestUtils';
|
||||
import {createChannel, createGuild} from '@app/api/channel/tests/ChannelTestUtils';
|
||||
import {resetChannelThreadsConfig, setChannelThreadsConfig} from '@app/api/channel/tests/ThreadTestUtils';
|
||||
import {ChannelThreadsRouteGuard} from '@app/api/channel/threads/ChannelThreadsRouteGuard';
|
||||
import {setCassandraQueryExecutorForTesting} from '@app/api/database/CassandraQueryExecution';
|
||||
import type {CassandraParams, PreparedQuery} from '@app/api/database/CassandraTypes';
|
||||
import {getCompiledChannelThreadsConfig} from '@app/api/experiment/ChannelThreadsGate';
|
||||
import {BotOnly, LoginRequired} from '@app/api/middleware/AuthMiddleware';
|
||||
import {RateLimitMiddleware} from '@app/api/middleware/RateLimitMiddleware';
|
||||
import {getInstanceConfigRepository} from '@app/api/middleware/ServiceSingletons';
|
||||
import {RateLimitConfigs} from '@app/api/RateLimitConfig';
|
||||
import {type ApiTestHarness, createApiTestHarness} from '@app/api/test/ApiTestHarness';
|
||||
import {InMemoryCassandraQueryExecutor} from '@app/api/test/InMemoryCassandraQueryExecutor';
|
||||
import {createBuilder} from '@app/api/test/TestRequestBuilder';
|
||||
import type {HonoApp} from '@app/api/types/HonoEnv';
|
||||
import {Validator} from '@app/api/Validator';
|
||||
import {
|
||||
applyChannelThreadsConfigUpdate,
|
||||
type ChannelThreadsConfigUpdateRequest,
|
||||
} from '@fluxer/schema/src/domains/admin/ChannelThreadsSchemas';
|
||||
import type {ChannelThreadsConfig} from '@fluxer/schema/src/domains/admin/ChannelThreadsSchemas';
|
||||
import {ChannelIdParam, GuildIdParam} from '@fluxer/schema/src/domains/common/CommonParamSchemas';
|
||||
import {afterAll, beforeAll, beforeEach, describe, expect, it} from 'vitest';
|
||||
import {z} from 'zod';
|
||||
@@ -96,6 +94,7 @@ describe('ChannelThreadsRouteGuard', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await harness.reset();
|
||||
resetChannelThreadsConfig();
|
||||
executor = new RecordingExecutor();
|
||||
setCassandraQueryExecutorForTesting(executor);
|
||||
owner = await createTestAccount(harness);
|
||||
@@ -109,10 +108,8 @@ describe('ChannelThreadsRouteGuard', () => {
|
||||
await harness.shutdown();
|
||||
});
|
||||
|
||||
async function setConfig(update: ChannelThreadsConfigUpdateRequest): Promise<void> {
|
||||
await getInstanceConfigRepository().updateChannelThreadsConfig((current) =>
|
||||
applyChannelThreadsConfigUpdate(current, update),
|
||||
);
|
||||
async function setConfig(update: Partial<ChannelThreadsConfig>): Promise<void> {
|
||||
await setChannelThreadsConfig({...getCompiledChannelThreadsConfig().config, ...update});
|
||||
}
|
||||
|
||||
async function snapshot(
|
||||
|
||||
Reference in new issue
Block a user