mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 21:45:31 +09:00
feat(guild): require opt-in for emoji and sticker cloning (#2712)
This commit is contained in:
1 parent
7b15e5be0f
commit
3affd295e8
63 files changed
+4189
-1752
No files matched your search
@@ -35,8 +35,8 @@ export const CloneAllowedToggle = observer(({guildId, kind}: CloneAllowedToggleP
|
||||
if (saving || !canManageGuild) return;
|
||||
setSaving(true);
|
||||
try {
|
||||
const feature = kind === 'emoji' ? GuildFeatures.CLONE_EMOJI_DISABLED : GuildFeatures.CLONE_STICKER_DISABLED;
|
||||
await GuildCommands.toggleFeature(guildId, feature, !nextAllowed);
|
||||
const feature = kind === 'emoji' ? GuildFeatures.CLONE_EMOJI_ENABLED : GuildFeatures.CLONE_STICKER_ENABLED;
|
||||
await GuildCommands.toggleFeature(guildId, feature, nextAllowed);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to toggle clone-${kind}-allowed for guild ${guildId}`, error);
|
||||
ModalCommands.push(
|
||||
@@ -52,21 +52,19 @@ export const CloneAllowedToggle = observer(({guildId, kind}: CloneAllowedToggleP
|
||||
}
|
||||
};
|
||||
const label =
|
||||
kind === 'emoji' ? (
|
||||
<Trans>Allow others to clone your emojis</Trans>
|
||||
) : (
|
||||
<Trans>Allow others to clone your stickers</Trans>
|
||||
);
|
||||
kind === 'emoji' ? <Trans>Let others clone your emojis</Trans> : <Trans>Let others clone your stickers</Trans>;
|
||||
const description =
|
||||
kind === 'emoji' ? (
|
||||
<Trans>
|
||||
When enabled, members of other communities can use the in-app one-click "Clone" shortcut on your custom emojis.
|
||||
This does not prevent them from saving the image and uploading it themselves.
|
||||
This is off until you turn it on. While it is on, members of other communities can use the in-app one-click
|
||||
"Clone" shortcut on your custom emojis. Turning it off does not prevent anyone from saving the image and
|
||||
uploading it themselves.
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans>
|
||||
When enabled, members of other communities can use the in-app one-click "Clone" shortcut on your custom
|
||||
stickers. This does not prevent them from saving the image and uploading it themselves.
|
||||
This is off until you turn it on. While it is on, members of other communities can use the in-app one-click
|
||||
"Clone" shortcut on your custom stickers. Turning it off does not prevent anyone from saving the image and
|
||||
uploading it themselves.
|
||||
</Trans>
|
||||
);
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {Guild} from '@app/features/guild/models/Guild';
|
||||
import {GuildFeatures} from '@fluxer/constants/src/GuildConstants';
|
||||
import type {Guild as WireGuild} from '@fluxer/schema/src/domains/guild/GuildResponseSchemas';
|
||||
import {describe, expect, test, vi} from 'vitest';
|
||||
|
||||
vi.mock('@app/features/app/state/RuntimeConfig', () => ({default: {localInstanceDomain: 'fluxer.test'}}));
|
||||
|
||||
const createGuild = (features: Array<string>): Guild =>
|
||||
new Guild({
|
||||
id: '1',
|
||||
name: 'Test Community',
|
||||
icon: null,
|
||||
features,
|
||||
roles: [],
|
||||
owner_id: '2',
|
||||
} as unknown as WireGuild);
|
||||
|
||||
describe('Guild clone permissions', () => {
|
||||
test('no features means cloning is not allowed', () => {
|
||||
const guild = createGuild([]);
|
||||
expect(guild.cloneEmojiAllowed).toBe(false);
|
||||
expect(guild.cloneStickerAllowed).toBe(false);
|
||||
});
|
||||
|
||||
test('the enabled features allow cloning', () => {
|
||||
const guild = createGuild([GuildFeatures.CLONE_EMOJI_ENABLED, GuildFeatures.CLONE_STICKER_ENABLED]);
|
||||
expect(guild.cloneEmojiAllowed).toBe(true);
|
||||
expect(guild.cloneStickerAllowed).toBe(true);
|
||||
});
|
||||
|
||||
test('each enabled feature only allows its own kind', () => {
|
||||
const emojiOnly = createGuild([GuildFeatures.CLONE_EMOJI_ENABLED]);
|
||||
expect(emojiOnly.cloneEmojiAllowed).toBe(true);
|
||||
expect(emojiOnly.cloneStickerAllowed).toBe(false);
|
||||
const stickerOnly = createGuild([GuildFeatures.CLONE_STICKER_ENABLED]);
|
||||
expect(stickerOnly.cloneEmojiAllowed).toBe(false);
|
||||
expect(stickerOnly.cloneStickerAllowed).toBe(true);
|
||||
});
|
||||
|
||||
test('the deprecated disabled features do not allow cloning', () => {
|
||||
const guild = createGuild([GuildFeatures.CLONE_EMOJI_DISABLED, GuildFeatures.CLONE_STICKER_DISABLED]);
|
||||
expect(guild.cloneEmojiAllowed).toBe(false);
|
||||
expect(guild.cloneStickerAllowed).toBe(false);
|
||||
});
|
||||
|
||||
test('the deprecated disabled features do not override the enabled features', () => {
|
||||
const guild = createGuild([
|
||||
GuildFeatures.CLONE_EMOJI_DISABLED,
|
||||
GuildFeatures.CLONE_STICKER_DISABLED,
|
||||
GuildFeatures.CLONE_EMOJI_ENABLED,
|
||||
GuildFeatures.CLONE_STICKER_ENABLED,
|
||||
]);
|
||||
expect(guild.cloneEmojiAllowed).toBe(true);
|
||||
expect(guild.cloneStickerAllowed).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -451,11 +451,11 @@ export class Guild {
|
||||
}
|
||||
|
||||
get cloneEmojiAllowed(): boolean {
|
||||
return !this.features.has(GuildFeatures.CLONE_EMOJI_DISABLED);
|
||||
return this.features.has(GuildFeatures.CLONE_EMOJI_ENABLED);
|
||||
}
|
||||
|
||||
get cloneStickerAllowed(): boolean {
|
||||
return !this.features.has(GuildFeatures.CLONE_STICKER_DISABLED);
|
||||
return this.features.has(GuildFeatures.CLONE_STICKER_ENABLED);
|
||||
}
|
||||
|
||||
get isLargeGuild(): boolean {
|
||||
|
||||
@@ -95,6 +95,14 @@ const STICKER_CLONING_DISABLED_DESCRIPTOR = msg({
|
||||
message: 'Sticker cloning disabled',
|
||||
comment: 'Audit log community feature label indicating sticker cloning is disabled.',
|
||||
});
|
||||
const EMOJI_CLONING_ENABLED_DESCRIPTOR = msg({
|
||||
message: 'Emoji cloning enabled',
|
||||
comment: 'Audit log community feature label indicating emoji cloning is enabled.',
|
||||
});
|
||||
const STICKER_CLONING_ENABLED_DESCRIPTOR = msg({
|
||||
message: 'Sticker cloning enabled',
|
||||
comment: 'Audit log community feature label indicating sticker cloning is enabled.',
|
||||
});
|
||||
const DETACHED_BANNER_DESCRIPTOR = msg({
|
||||
message: 'Detached banner',
|
||||
comment: 'Audit log community feature label for detached banner layout support.',
|
||||
@@ -425,6 +433,8 @@ const featureLabelMap: Record<string, MessageDescriptor> = {
|
||||
[GuildFeatures.BANNER]: BANNER_DESCRIPTOR,
|
||||
[GuildFeatures.CLONE_EMOJI_DISABLED]: EMOJI_CLONING_DISABLED_DESCRIPTOR,
|
||||
[GuildFeatures.CLONE_STICKER_DISABLED]: STICKER_CLONING_DISABLED_DESCRIPTOR,
|
||||
[GuildFeatures.CLONE_EMOJI_ENABLED]: EMOJI_CLONING_ENABLED_DESCRIPTOR,
|
||||
[GuildFeatures.CLONE_STICKER_ENABLED]: STICKER_CLONING_ENABLED_DESCRIPTOR,
|
||||
[GuildFeatures.DETACHED_BANNER]: DETACHED_BANNER_DESCRIPTOR,
|
||||
[GuildFeatures.INVITE_SPLASH]: INVITE_SPLASH_DESCRIPTOR,
|
||||
[GuildFeatures.INVITES_DISABLED]: INVITES_DISABLED_DESCRIPTOR,
|
||||
|
||||
Reference in new issue
Block a user