Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be71931a81 |
@@ -47,8 +47,12 @@ import {
|
|||||||
recentForwardTargetsAtom,
|
recentForwardTargetsAtom,
|
||||||
addRecentForwardTarget,
|
addRecentForwardTarget,
|
||||||
} from '../../../state/recentForwardTargets';
|
} from '../../../state/recentForwardTargets';
|
||||||
import { buildForwardContent, buildPlaintextAttachmentContent } from './forwardContent';
|
import {
|
||||||
import { useLocalRoomNames } from '../../../hooks/useRoomMeta';
|
buildForwardContent,
|
||||||
|
buildPlaintextAttachmentContent,
|
||||||
|
forwardEncryptionWarning,
|
||||||
|
} from './forwardContent';
|
||||||
|
import { useLocalRoomNames, getLocalRoomName } from '../../../hooks/useRoomMeta';
|
||||||
|
|
||||||
type RoomRowProps = {
|
type RoomRowProps = {
|
||||||
room: Room;
|
room: Room;
|
||||||
@@ -275,6 +279,14 @@ export function ForwardMessageDialog({ mEvent, onClose }: Props) {
|
|||||||
// Selection persists across query changes: a room selected then filtered out
|
// Selection persists across query changes: a room selected then filtered out
|
||||||
// of the rendered slice stays selected.
|
// of the rendered slice stays selected.
|
||||||
const [selectedRoomIds, setSelectedRoomIds] = useState<Set<string>>(new Set());
|
const [selectedRoomIds, setSelectedRoomIds] = useState<Set<string>>(new Set());
|
||||||
|
const encryptionWarning = forwardEncryptionWarning(
|
||||||
|
!!mx.getRoom(mEvent.getRoomId() ?? '')?.hasEncryptionStateEvent(),
|
||||||
|
[...selectedRoomIds]
|
||||||
|
.map((id) => mx.getRoom(id))
|
||||||
|
.filter((r): r is Room => !!r && !r.hasEncryptionStateEvent())
|
||||||
|
// The name the user sees (their own "Rename for me" name, if set).
|
||||||
|
.map((r) => getLocalRoomName(mx, r.roomId) ?? r.name),
|
||||||
|
);
|
||||||
|
|
||||||
const toggleRoom = useCallback((roomId: string) => {
|
const toggleRoom = useCallback((roomId: string) => {
|
||||||
setSelectedRoomIds((prev) => {
|
setSelectedRoomIds((prev) => {
|
||||||
@@ -590,7 +602,13 @@ export function ForwardMessageDialog({ mEvent, onClose }: Props) {
|
|||||||
shrink="No"
|
shrink="No"
|
||||||
direction="Column"
|
direction="Column"
|
||||||
style={{ padding: `${config.space.S200} ${config.space.S400}` }}
|
style={{ padding: `${config.space.S200} ${config.space.S400}` }}
|
||||||
|
gap="200"
|
||||||
>
|
>
|
||||||
|
{encryptionWarning && (
|
||||||
|
<Text size="T200" role="note" style={{ color: color.Warning.Main }}>
|
||||||
|
{encryptionWarning}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="Primary"
|
variant="Primary"
|
||||||
size="400"
|
size="400"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { test } from 'node:test';
|
import { test } from 'node:test';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import { MatrixClient, MatrixEvent } from 'matrix-js-sdk';
|
import { MatrixClient, MatrixEvent } from 'matrix-js-sdk';
|
||||||
import { buildForwardContent, getForwardedMeta } from './forwardContent';
|
import { buildForwardContent, forwardEncryptionWarning, getForwardedMeta } from './forwardContent';
|
||||||
|
|
||||||
// Pure content builder buildForwardContent: refuses undecryptable events, forwards
|
// Pure content builder buildForwardContent: refuses undecryptable events, forwards
|
||||||
// the latest edit (`m.new_content`), and strips reply fallbacks + `m.relates_to`.
|
// the latest edit (`m.new_content`), and strips reply fallbacks + `m.relates_to`.
|
||||||
@@ -171,3 +171,16 @@ test('getForwardedMeta rejects malformed metadata', () => {
|
|||||||
assert.equal(getForwardedMeta({ 'io.lotus.forwarded': { sender: 1 } }), undefined);
|
assert.equal(getForwardedMeta({ 'io.lotus.forwarded': { sender: 1 } }), undefined);
|
||||||
assert.equal(getForwardedMeta({}), undefined);
|
assert.equal(getForwardedMeta({}), undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('forwardEncryptionWarning: only from an encrypted room into unencrypted ones (#330)', () => {
|
||||||
|
assert.equal(forwardEncryptionWarning(false, ['general']), undefined);
|
||||||
|
assert.equal(forwardEncryptionWarning(true, []), undefined);
|
||||||
|
assert.match(
|
||||||
|
forwardEncryptionWarning(true, ['general']) ?? '',
|
||||||
|
/^general isn't encrypted\..*that room, along with who originally wrote it\.$/,
|
||||||
|
);
|
||||||
|
assert.match(
|
||||||
|
forwardEncryptionWarning(true, ['a', 'b']) ?? '',
|
||||||
|
/^2 of the rooms you picked aren't encrypted\..*those rooms/,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|||||||
@@ -122,3 +122,23 @@ export async function buildPlaintextAttachmentContent(
|
|||||||
|
|
||||||
return plainContent;
|
return plainContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [Gitea #330] The note shown when forwarding out of an encrypted room into
|
||||||
|
* rooms that aren't: the text (and a re-uploaded attachment) becomes readable
|
||||||
|
* by the server, and the original author is shown with it. Undefined when
|
||||||
|
* there's nothing to warn about.
|
||||||
|
*/
|
||||||
|
export function forwardEncryptionWarning(
|
||||||
|
sourceEncrypted: boolean,
|
||||||
|
unencryptedDestNames: string[],
|
||||||
|
): string | undefined {
|
||||||
|
if (!sourceEncrypted || unencryptedDestNames.length === 0) return undefined;
|
||||||
|
const where =
|
||||||
|
unencryptedDestNames.length === 1
|
||||||
|
? `${unencryptedDestNames[0]} isn't encrypted.`
|
||||||
|
: `${unencryptedDestNames.length} of the rooms you picked aren't encrypted.`;
|
||||||
|
return `${where} The forwarded message (and any attachment) will be readable by the server and everyone in ${
|
||||||
|
unencryptedDestNames.length === 1 ? 'that room' : 'those rooms'
|
||||||
|
}, along with who originally wrote it.`;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user