Skip to content
Merged
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
2 changes: 2 additions & 0 deletions src/db/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ export interface ServerConfigRecord {
spam_filter_sensitivity: SpamSensitivity;
/** Whether members may use a video avatar or banner, where the worker can transcode one. */
video_profiles_enabled: boolean;
/** Whether messages here may show other Gryt servers' custom emoji. Off: they load from another host. */
external_emojis_enabled: boolean;
is_configured: boolean;
created_at: Date;
updated_at: Date;
Expand Down
5 changes: 5 additions & 0 deletions src/db/sqlite/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ function createSchema(d: DatabaseSync): void {
spam_filter INTEGER NOT NULL DEFAULT 1,
spam_sensitivity TEXT NOT NULL DEFAULT 'normal',
video_profiles INTEGER NOT NULL DEFAULT 1,
external_emojis INTEGER NOT NULL DEFAULT 0,
is_configured INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
Expand Down Expand Up @@ -946,6 +947,10 @@ function runMigrations(d: DatabaseSync): void {
if (!hasColumn(d, "server_config", "video_profiles")) {
d.exec("ALTER TABLE server_config ADD COLUMN video_profiles INTEGER NOT NULL DEFAULT 1");
}
// Off by default: another server's emoji loads from that host, which then sees who read it (GRYT-1660).
if (!hasColumn(d, "server_config", "external_emojis")) {
d.exec("ALTER TABLE server_config ADD COLUMN external_emojis INTEGER NOT NULL DEFAULT 0");
}

// Stored and handed back whole, and never read here. One column rather than a
// key beside a signature, so the two cannot be mixed between members.
Expand Down
3 changes: 3 additions & 0 deletions src/db/sqlite/servers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ function rowToConfig(r: Record<string, unknown>): ServerConfigRecord {
spam_filter_enabled: (r.spam_filter as number) !== 0,
spam_filter_sensitivity: normalizeSpamSensitivity(r.spam_sensitivity),
video_profiles_enabled: (r.video_profiles as number) !== 0,
external_emojis_enabled: (r.external_emojis as number) === 1,
is_configured: (r.is_configured as number) === 1,
created_at: fromIso(r.created_at as string),
updated_at: fromIso(r.updated_at as string),
Expand Down Expand Up @@ -243,6 +244,7 @@ export async function updateServerConfig(patch: {
spamFilter?: boolean;
spamSensitivity?: SpamSensitivity;
videoProfiles?: boolean;
externalEmojis?: boolean;
isConfigured?: boolean;
}): Promise<ServerConfigRecord> {
const db = getSqliteDb();
Expand Down Expand Up @@ -273,6 +275,7 @@ export async function updateServerConfig(patch: {
spamFilter: { col: "spam_filter", transform: (v) => v ? 1 : 0 },
spamSensitivity: { col: "spam_sensitivity", transform: (v) => normalizeSpamSensitivity(v) },
videoProfiles: { col: "video_profiles", transform: (v) => v ? 1 : 0 },
externalEmojis: { col: "external_emojis", transform: (v) => v ? 1 : 0 },
isConfigured: { col: "is_configured", transform: (v) => v ? 1 : 0 },
};

Expand Down
45 changes: 45 additions & 0 deletions src/settings/externalEmojis.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import assert from "node:assert/strict";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { after, before, describe, it } from "node:test";

import { initSqlite } from "../db/sqlite/connection";
import { createServerConfigIfNotExists, getServerConfig } from "../db/sqlite/servers";
import { applyServerSettings, settingsView } from "./serverSettings";

let dir: string;

before(async () => {
dir = mkdtempSync(join(tmpdir(), "gryt-ext-emoji-"));
process.env.DATA_DIR = dir;
await initSqlite();
await createServerConfigIfNotExists();
});

after(() => {
delete process.env.DATA_DIR;
rmSync(dir, { recursive: true, force: true });
});

describe("other servers' emoji (GRYT-1660)", () => {
it("is off until the owner turns it on, and stays as set", async () => {
const cfg = await getServerConfig();
assert.ok(cfg);
assert.equal(cfg.external_emojis_enabled, false);
assert.equal(settingsView(cfg, "s", true).externalEmojis, false);

const on = await applyServerSettings({ externalEmojis: true }, { serverUserId: null, via: "management" });
assert.equal(on.external_emojis_enabled, true);
assert.equal(settingsView(on, "s", true).externalEmojis, true);

// Leaving it out of a patch changes nothing, and anything but a boolean is ignored.
const untouched = await applyServerSettings({ displayName: "Elsewhere" }, { serverUserId: null, via: "management" });
assert.equal(untouched.external_emojis_enabled, true);
const junk = await applyServerSettings({ externalEmojis: "yes" as unknown as boolean }, { serverUserId: null, via: "management" });
assert.equal(junk.external_emojis_enabled, true);

const off = await applyServerSettings({ externalEmojis: false }, { serverUserId: null, via: "management" });
assert.equal(off.external_emojis_enabled, false);
});
});
4 changes: 4 additions & 0 deletions src/settings/serverSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface SettingsPatch {
spamFilter?: boolean;
spamSensitivity?: string;
videoProfiles?: boolean;
externalEmojis?: boolean;
}

/** Who asked for the change, for the audit trail. */
Expand Down Expand Up @@ -106,6 +107,7 @@ export async function applyServerSettings(
: undefined;

const videoProfiles: boolean | undefined = typeof patch.videoProfiles === "boolean" ? patch.videoProfiles : undefined;
const externalEmojis: boolean | undefined = typeof patch.externalEmojis === "boolean" ? patch.externalEmojis : undefined;

const updated = await updateServerConfig({
displayName: displayName === undefined ? undefined : (displayName.length > 0 ? displayName : null),
Expand All @@ -124,6 +126,7 @@ export async function applyServerSettings(
spamFilter,
spamSensitivity,
videoProfiles,
externalEmojis,
});

if (systemChannelId !== undefined) invalidateSystemChannelCache();
Expand Down Expand Up @@ -175,6 +178,7 @@ export function settingsView(cfg: ServerConfigRecord, serverId: string, isOwner:
spamFilter: cfg.spam_filter_enabled !== false,
spamSensitivity: cfg.spam_filter_sensitivity ?? "normal",
videoProfiles: cfg.video_profiles_enabled !== false,
externalEmojis: cfg.external_emojis_enabled === true,
// What this host can do, so settings can say why a switch is off rather than hide it.
media: { checked: workerClearsQuarantine(), video: workerTranscodesVideo() },
};
Expand Down
1 change: 1 addition & 0 deletions src/socket/handlers/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ export function registerAdminHandlers(ctx: HandlerContext): EventHandlerMap {
spamFilter?: boolean;
spamSensitivity?: string;
videoProfiles?: boolean;
externalEmojis?: boolean;
}) => {
try {
const rl = rlCheck("server:settings:update", ctx, RL_SETTINGS);
Expand Down
4 changes: 4 additions & 0 deletions src/socket/utils/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ export async function sendServerDetails(socket: Socket, clientsInfo: Clients, in
let cfgAvatarMaxBytes: number = DEFAULT_AVATAR_MAX_BYTES;
let cfgUploadMaxBytes: number = DEFAULT_UPLOAD_MAX_BYTES;
let cfgVideoProfiles = true;
let cfgExternalEmojis = false;
let isOwner = false;
let role = FALLBACK_ROLE_ID;
let roleIds: string[] = [];
Expand All @@ -391,6 +392,7 @@ export async function sendServerDetails(socket: Socket, clientsInfo: Clients, in
if (typeof cfg?.avatar_max_bytes === "number") cfgAvatarMaxBytes = cfg.avatar_max_bytes;
if (typeof cfg?.upload_max_bytes === "number") cfgUploadMaxBytes = cfg.upload_max_bytes;
cfgVideoProfiles = cfg?.video_profiles_enabled !== false;
cfgExternalEmojis = cfg?.external_emojis_enabled === true;
isOwner = !!(cfg?.owner_gryt_user_id && cfg.owner_gryt_user_id === client.grytUserId);
if (client.serverUserId && !client.serverUserId.startsWith("temp_")) {
const standing = await getEffectiveStanding(client.serverUserId, client.grytUserId);
Expand Down Expand Up @@ -445,6 +447,8 @@ export async function sendServerDetails(socket: Socket, clientsInfo: Clients, in
/** Uploads go through the worker's sandbox first, and whether a video avatar or banner is taken. */
uploads_checked: workerClearsQuarantine(),
video_profiles: workerTranscodesVideo() && cfgVideoProfiles,
/** Messages here may show other Gryt servers' custom emoji. */
external_emojis: cfgExternalEmojis,
version: process.env.SERVER_VERSION || "1.0.0",
/** What code sits between a member and the people they talk to, so it is
not configurable. No version: that names which known problem applies. */
Expand Down
Loading