Skip to content

Commit ffbb471

Browse files
authored
Add authenticated media to getAvatarURL in room and room-member models (#4616)
1 parent 07f97d7 commit ffbb471

File tree

4 files changed

+108
-2
lines changed

4 files changed

+108
-2
lines changed

spec/unit/room-member.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,40 @@ describe("RoomMember", function () {
6565
const url = member.getAvatarUrl(hsUrl, 64, 64, "crop", false, false);
6666
expect(url).toEqual(null);
6767
});
68+
69+
it("should return unauthenticated media URL if useAuthentication is not set", function () {
70+
member.events.member = utils.mkEvent({
71+
event: true,
72+
type: "m.room.member",
73+
skey: userA,
74+
room: roomId,
75+
user: userA,
76+
content: {
77+
membership: KnownMembership.Join,
78+
avatar_url: "mxc://flibble/wibble",
79+
},
80+
});
81+
const url = member.getAvatarUrl(hsUrl, 1, 1, "", false, false);
82+
// Check for unauthenticated media prefix
83+
expect(url?.indexOf("/_matrix/media/v3/")).not.toEqual(-1);
84+
});
85+
86+
it("should return authenticated media URL if useAuthentication=true", function () {
87+
member.events.member = utils.mkEvent({
88+
event: true,
89+
type: "m.room.member",
90+
skey: userA,
91+
room: roomId,
92+
user: userA,
93+
content: {
94+
membership: KnownMembership.Join,
95+
avatar_url: "mxc://flibble/wibble",
96+
},
97+
});
98+
const url = member.getAvatarUrl(hsUrl, 1, 1, "", false, false, true);
99+
// Check for authenticated media prefix
100+
expect(url?.indexOf("/_matrix/client/v1/media/")).not.toEqual(-1);
101+
});
68102
});
69103

70104
describe("setPowerLevelEvent", function () {

spec/unit/room.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,48 @@ describe("Room", function () {
299299
const url = room.getAvatarUrl(hsUrl, 64, 64, "crop", false);
300300
expect(url).toEqual(null);
301301
});
302+
303+
it("should return unauthenticated media URL if useAuthentication is not set", function () {
304+
// @ts-ignore - mocked doesn't handle overloads sanely
305+
mocked(room.currentState.getStateEvents).mockImplementation(function (type, key) {
306+
if (type === EventType.RoomAvatar && key === "") {
307+
return utils.mkEvent({
308+
event: true,
309+
type: EventType.RoomAvatar,
310+
skey: "",
311+
room: roomId,
312+
user: userA,
313+
content: {
314+
url: "mxc://flibble/wibble",
315+
},
316+
});
317+
}
318+
});
319+
const url = room.getAvatarUrl(hsUrl, 100, 100, "scale");
320+
// Check for unauthenticated media prefix
321+
expect(url?.indexOf("/_matrix/media/v3/")).not.toEqual(-1);
322+
});
323+
324+
it("should return authenticated media URL if useAuthentication=true", function () {
325+
// @ts-ignore - mocked doesn't handle overloads sanely
326+
mocked(room.currentState.getStateEvents).mockImplementation(function (type, key) {
327+
if (type === EventType.RoomAvatar && key === "") {
328+
return utils.mkEvent({
329+
event: true,
330+
type: EventType.RoomAvatar,
331+
skey: "",
332+
room: roomId,
333+
user: userA,
334+
content: {
335+
url: "mxc://flibble/wibble",
336+
},
337+
});
338+
}
339+
});
340+
const url = room.getAvatarUrl(hsUrl, 100, 100, "scale", undefined, true);
341+
// Check for authenticated media prefix
342+
expect(url?.indexOf("/_matrix/client/v1/media/")).not.toEqual(-1);
343+
});
302344
});
303345

304346
describe("getMember", function () {

src/models/room-member.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,11 @@ export class RoomMember extends TypedEventEmitter<RoomMemberEvent, RoomMemberEve
368368
* If false, any non-matrix content URLs will be ignored. Setting this option to
369369
* true will expose URLs that, if fetched, will leak information about the user
370370
* to anyone who they share a room with.
371+
* @param useAuthentication - (optional) If true, the caller supports authenticated
372+
* media and wants an authentication-required URL. Note that server support for
373+
* authenticated media will not be checked - it is the caller's responsibility
374+
* to do so before calling this function. Note also that useAuthentication
375+
* implies allowRedirects. Defaults to false (unauthenticated endpoints).
371376
* @returns the avatar URL or null.
372377
*/
373378
public getAvatarUrl(
@@ -377,13 +382,23 @@ export class RoomMember extends TypedEventEmitter<RoomMemberEvent, RoomMemberEve
377382
resizeMethod: string,
378383
allowDefault = true,
379384
allowDirectLinks: boolean,
385+
useAuthentication: boolean = false,
380386
): string | null {
381387
const rawUrl = this.getMxcAvatarUrl();
382388

383389
if (!rawUrl && !allowDefault) {
384390
return null;
385391
}
386-
const httpUrl = getHttpUriForMxc(baseUrl, rawUrl, width, height, resizeMethod, allowDirectLinks);
392+
const httpUrl = getHttpUriForMxc(
393+
baseUrl,
394+
rawUrl,
395+
width,
396+
height,
397+
resizeMethod,
398+
allowDirectLinks,
399+
undefined,
400+
useAuthentication,
401+
);
387402
if (httpUrl) {
388403
return httpUrl;
389404
}

src/models/room.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1661,6 +1661,11 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
16611661
* "crop" or "scale".
16621662
* @param allowDefault - True to allow an identicon for this room if an
16631663
* avatar URL wasn't explicitly set. Default: true. (Deprecated)
1664+
* @param useAuthentication - (optional) If true, the caller supports authenticated
1665+
* media and wants an authentication-required URL. Note that server support for
1666+
* authenticated media will not be checked - it is the caller's responsibility
1667+
* to do so before calling this function. Note also that useAuthentication
1668+
* implies allowRedirects. Defaults to false (unauthenticated endpoints).
16641669
* @returns the avatar URL or null.
16651670
*/
16661671
public getAvatarUrl(
@@ -1669,6 +1674,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
16691674
height: number,
16701675
resizeMethod: ResizeMethod,
16711676
allowDefault = true,
1677+
useAuthentication: boolean = false,
16721678
): string | null {
16731679
const roomAvatarEvent = this.currentState.getStateEvents(EventType.RoomAvatar, "");
16741680
if (!roomAvatarEvent && !allowDefault) {
@@ -1677,7 +1683,16 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
16771683

16781684
const mainUrl = roomAvatarEvent ? roomAvatarEvent.getContent().url : null;
16791685
if (mainUrl) {
1680-
return getHttpUriForMxc(baseUrl, mainUrl, width, height, resizeMethod);
1686+
return getHttpUriForMxc(
1687+
baseUrl,
1688+
mainUrl,
1689+
width,
1690+
height,
1691+
resizeMethod,
1692+
undefined,
1693+
undefined,
1694+
useAuthentication,
1695+
);
16811696
}
16821697

16831698
return null;

0 commit comments

Comments
 (0)