Room purge fixes

This commit is contained in:
N Pex 2023-01-31 09:39:30 +00:00
parent e4597dd7b4
commit f34144557a
2 changed files with 93 additions and 180 deletions

View file

@ -1018,7 +1018,6 @@ export default {
}, },
handleScrolledToTop() { handleScrolledToTop() {
console.log("@top");
if ( if (
this.timelineWindow && this.timelineWindow &&
this.timelineWindow.canPaginate(EventTimeline.BACKWARDS) && this.timelineWindow.canPaginate(EventTimeline.BACKWARDS) &&
@ -1045,7 +1044,6 @@ export default {
}, },
handleScrolledToBottom(scrollToEnd) { handleScrolledToBottom(scrollToEnd) {
console.log("@bottom");
if ( if (
this.timelineWindow && this.timelineWindow &&
this.timelineWindow.canPaginate(EventTimeline.FORWARDS) && this.timelineWindow.canPaginate(EventTimeline.FORWARDS) &&
@ -1287,7 +1285,6 @@ export default {
* Start/restart the timer to Read Receipts. * Start/restart the timer to Read Receipts.
*/ */
restartRRTimer() { restartRRTimer() {
console.log("Restart RR timer");
this.stopRRTimer(); this.stopRRTimer();
let eventIdFirst = null; let eventIdFirst = null;
@ -1307,7 +1304,6 @@ export default {
}, },
rrTimerElapsed(eventIdFirst, eventIdLast) { rrTimerElapsed(eventIdFirst, eventIdLast) {
console.log("RR timer elapsed", eventIdFirst, eventIdLast);
this.rrTimer = null; this.rrTimer = null;
this.sendRR(eventIdFirst, eventIdLast); this.sendRR(eventIdFirst, eventIdLast);
this.restartRRTimer(); this.restartRRTimer();

View file

@ -5,8 +5,8 @@ import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
import util from "../plugins/utils"; import util from "../plugins/utils";
import User from "../models/user"; import User from "../models/user";
const LocalStorageCryptoStore = require("matrix-js-sdk/lib/crypto/store/localStorage-crypto-store") const LocalStorageCryptoStore =
.LocalStorageCryptoStore; require("matrix-js-sdk/lib/crypto/store/localStorage-crypto-store").LocalStorageCryptoStore;
export default { export default {
install(Vue, options) { install(Vue, options) {
@ -141,9 +141,7 @@ export default {
if (user.device_id) { if (user.device_id) {
data.device_id = user.device_id; data.device_id = user.device_id;
} }
promiseLogin = tempMatrixClient promiseLogin = tempMatrixClient.login("m.login.password", data).then((response) => {
.login("m.login.password", data)
.then((response) => {
var u = Object.assign({}, response); var u = Object.assign({}, response);
if (user.is_guest) { if (user.is_guest) {
// Copy over needed properties // Copy over needed properties
@ -261,11 +259,7 @@ export default {
return matrixClient; return matrixClient;
} else { } else {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
matrixClient.once("sync", function( matrixClient.once("sync", function (state, ignoredprevState, ignoredres) {
state,
ignoredprevState,
ignoredres
) {
console.log(state); // state will be 'PREPARED' when the client is ready to use console.log(state); // state will be 'PREPARED' when the client is ready to use
if (state == "PREPARED") { if (state == "PREPARED") {
resolve(matrixClient); resolve(matrixClient);
@ -293,11 +287,7 @@ export default {
if (this.ready) { if (this.ready) {
return Promise.resolve(this.currentUser); return Promise.resolve(this.currentUser);
} }
return this.$store.dispatch( return this.$store.dispatch("login", this.currentUser || new User(this.$config.defaultServer, "", "", true));
"login",
this.currentUser ||
new User(this.$config.defaultServer, "", "", true)
);
}, },
addMatrixClientListeners(client) { addMatrixClientListeners(client) {
@ -337,13 +327,7 @@ export default {
Vue.set( Vue.set(
room, room,
"avatar", "avatar",
room.getAvatarUrl( room.getAvatarUrl(this.matrixClient.getHomeserverUrl(), 80, 80, "scale", true)
this.matrixClient.getHomeserverUrl(),
80,
80,
"scale",
true
)
); );
} }
} }
@ -351,26 +335,20 @@ export default {
case "m.room.member": case "m.room.member":
{ {
if ( if (this.currentRoom && event.getRoomId() == this.currentRoom.roomId) {
this.currentRoom &&
event.getRoomId() == this.currentRoom.roomId
) {
// Don't use this.currentRoomId, may be an alias. We need the real id! // Don't use this.currentRoomId, may be an alias. We need the real id!
if (( if (
event.getContent().membership == "leave" && (event.getContent().membership == "leave" &&
(event.getPrevContent() || {}).membership == "join" && (event.getPrevContent() || {}).membership == "join" &&
event.getStateKey() == this.currentUserId && event.getStateKey() == this.currentUserId &&
event.getSender() != this.currentUserId event.getSender() != this.currentUserId) ||
) || (event.getContent().membership == "ban" && event.getStateKey() == this.currentUserId)) { (event.getContent().membership == "ban" && event.getStateKey() == this.currentUserId)
) {
// We were kicked or banned // We were kicked or banned
// If this is a live event (not just backpaging) then redirect to goodbye! // If this is a live event (not just backpaging) then redirect to goodbye!
if (this.matrixClientReady) { if (this.matrixClientReady) {
const wasPurged = const wasPurged = event.getContent().reason == "Room Deleted";
event.getContent().reason == "Room Deleted"; this.$navigation.push({ name: "Goodbye", params: { roomWasPurged: wasPurged } }, -1);
this.$navigation.push(
{ name: "Goodbye", params: { roomWasPurged: wasPurged } },
-1
);
} }
} }
} }
@ -414,15 +392,15 @@ export default {
this.$store.commit("setUser", user); this.$store.commit("setUser", user);
// Login again // Login again
this.login(user).catch(error => { this.login(user).catch((error) => {
if (error.data.errcode ==='M_FORBIDDEN' && this.currentUser.is_guest) { if (error.data.errcode === "M_FORBIDDEN" && this.currentUser.is_guest) {
// Guest account and password don't work. We are in a strange state, probably because // Guest account and password don't work. We are in a strange state, probably because
// of server cleanup of accounts or similar. Wipe account and restart... // of server cleanup of accounts or similar. Wipe account and restart...
this.$store.commit("setUser", null); this.$store.commit("setUser", null);
} }
this.$store.commit("setCurrentRoomId", null); this.$store.commit("setCurrentRoomId", null);
this.$navigation.push({ path: "/login" }, -1); this.$navigation.push({ path: "/login" }, -1);
}) });
} else { } else {
this.$store.commit("setUser", null); this.$store.commit("setUser", null);
this.$store.commit("setCurrentRoomId", null); this.$store.commit("setCurrentRoomId", null);
@ -435,24 +413,11 @@ export default {
// each time! // each time!
var updatedRooms = this.matrixClient.getVisibleRooms(); var updatedRooms = this.matrixClient.getVisibleRooms();
updatedRooms = updatedRooms.filter((room) => { updatedRooms = updatedRooms.filter((room) => {
return ( return room.selfMembership && (room.selfMembership == "invite" || room.selfMembership == "join");
room.selfMembership &&
(room.selfMembership == "invite" || room.selfMembership == "join")
);
}); });
updatedRooms.forEach((room) => { updatedRooms.forEach((room) => {
if (!room.avatar) { if (!room.avatar) {
Vue.set( Vue.set(room, "avatar", room.getAvatarUrl(this.matrixClient.getHomeserverUrl(), 80, 80, "scale", true));
room,
"avatar",
room.getAvatarUrl(
this.matrixClient.getHomeserverUrl(),
80,
80,
"scale",
true
)
);
} }
}); });
Vue.set(this, "rooms", updatedRooms); Vue.set(this, "rooms", updatedRooms);
@ -491,15 +456,9 @@ export default {
var ids = {}; var ids = {};
const ret = []; const ret = [];
for (const room of this.rooms) { for (const room of this.rooms) {
if ( if (room.selfMembership == "join" && this.getRoomJoinRule(room) == "invite") {
room.selfMembership == "join" &&
this.getRoomJoinRule(room) == "invite"
) {
for (const member of room.getJoinedMembers()) { for (const member of room.getJoinedMembers()) {
if ( if (member.userId != this.currentUserId && !ids[member.userId]) {
member.userId != this.currentUserId &&
!ids[member.userId]
) {
ids[member.userId] = member; ids[member.userId] = member;
ret.push(member); ret.push(member);
} }
@ -516,10 +475,7 @@ export default {
getRoomJoinRule(room) { getRoomJoinRule(room) {
if (room) { if (room) {
const joinRules = room.currentState.getStateEvents( const joinRules = room.currentState.getStateEvents("m.room.join_rules", "");
"m.room.join_rules",
""
);
return joinRules && joinRules.getContent().join_rule; return joinRules && joinRules.getContent().join_rule;
} }
return null; return null;
@ -527,14 +483,8 @@ export default {
getRoomHistoryVisibility(room) { getRoomHistoryVisibility(room) {
if (room) { if (room) {
const historyVisibility = room.currentState.getStateEvents( const historyVisibility = room.currentState.getStateEvents("m.room.history_visibility", "");
"m.room.history_visibility", return historyVisibility && historyVisibility.getContent().history_visibility;
""
);
return (
historyVisibility &&
historyVisibility.getContent().history_visibility
);
} }
return null; return null;
}, },
@ -551,21 +501,13 @@ export default {
kickUser(roomId, userId) { kickUser(roomId, userId) {
if (this.matrixClient && roomId && userId) { if (this.matrixClient && roomId && userId) {
this.matrixClient.kick( this.matrixClient.kick(roomId, userId, "");
roomId,
userId,
""
)
} }
}, },
banUser(roomId, userId) { banUser(roomId, userId) {
if (this.matrixClient && roomId && userId) { if (this.matrixClient && roomId && userId) {
this.matrixClient.ban( this.matrixClient.ban(roomId, userId, "");
roomId,
userId,
""
)
} }
}, },
@ -624,22 +566,13 @@ export default {
return; return;
} }
const timelineWindow = new TimelineWindow( const timelineWindow = new TimelineWindow(this.matrixClient, room.getUnfilteredTimelineSet(), {});
this.matrixClient,
room.getUnfilteredTimelineSet(),
{}
);
const self = this; const self = this;
//console.log("Purge: set invite only"); //console.log("Purge: set invite only");
statusCallback(this.$t("room.purge_set_room_state")); statusCallback(this.$t("room.purge_set_room_state"));
this.matrixClient this.matrixClient
.sendStateEvent( .sendStateEvent(roomId, "m.room.join_rules", { join_rule: "invite" }, "")
roomId,
"m.room.join_rules",
{ join_rule: "invite" },
""
)
.then(() => { .then(() => {
//console.log("Purge: forbid guest access"); //console.log("Purge: forbid guest access");
return this.matrixClient.sendStateEvent( return this.matrixClient.sendStateEvent(
@ -651,13 +584,9 @@ export default {
}) })
.then(() => { .then(() => {
//console.log("Purge: set history visibility to 'joined'"); //console.log("Purge: set history visibility to 'joined'");
return this.matrixClient.sendStateEvent( return this.matrixClient.sendStateEvent(roomId, "m.room.history_visibility", {
roomId,
"m.room.history_visibility",
{
history_visibility: "joined", history_visibility: "joined",
} });
);
}) })
.then(() => { .then(() => {
//console.log("Purge: create timeline"); //console.log("Purge: create timeline");
@ -667,10 +596,11 @@ export default {
const getMoreIfAvailable = function _getMoreIfAvailable() { const getMoreIfAvailable = function _getMoreIfAvailable() {
if (timelineWindow.canPaginate(EventTimeline.BACKWARDS)) { if (timelineWindow.canPaginate(EventTimeline.BACKWARDS)) {
//console.log("Purge: page back"); //console.log("Purge: page back");
return timelineWindow return timelineWindow.paginate(EventTimeline.BACKWARDS, 100, true, 5).then((gotmore) => {
.paginate(EventTimeline.BACKWARDS, 100, true, 5) if (gotmore) {
.then((ignoredsuccess) => {
return _getMoreIfAvailable.call(self); return _getMoreIfAvailable.call(self);
}
return Promise.resolve("Done");
}); });
} else { } else {
return Promise.resolve("Done"); return Promise.resolve("Done");
@ -685,18 +615,9 @@ export default {
this.matrixClient.setGlobalErrorOnUnknownDevices(false); this.matrixClient.setGlobalErrorOnUnknownDevices(false);
var redactionPromises = []; var redactionPromises = [];
timelineWindow.getEvents().forEach((event) => { timelineWindow.getEvents().forEach((event) => {
if ( if (!event.isRedacted() && !event.isRedaction() && !event.isState()) {
!event.isRedacted() &&
!event.isRedaction() &&
!event.isState()
) {
// Redact! // Redact!
redactionPromises.push( redactionPromises.push(this.matrixClient.redactEvent(event.getRoomId(), event.getId()));
this.matrixClient.redactEvent(
event.getRoomId(),
event.getId()
)
);
} }
}); });
return Promise.all(redactionPromises); return Promise.all(redactionPromises);
@ -706,27 +627,44 @@ export default {
statusCallback(this.$t("room.purge_removing_members")); statusCallback(this.$t("room.purge_removing_members"));
var joined = room.getMembersWithMembership("join"); var joined = room.getMembersWithMembership("join");
var invited = room.getMembersWithMembership("invite"); var invited = room.getMembersWithMembership("invite");
var members = joined.concat(invited); var allMembers = joined.concat(invited);
var kickPromises = []; function sleep(ms) {
members.forEach((member) => { return new Promise(resolve => setTimeout(resolve, ms));
if (member.userId != self.currentUserId) {
kickPromises.push(
this.matrixClient.kick(
roomId,
member.userId,
"Room Deleted"
)
);
} }
});
return Promise.all(kickPromises); const kickFirstMember = (members) => {
//console.log(`Kicking ${members.length} members`);
if (members.length == 0) {
return Promise.resolve(true);
}
const member = members[0];
if (member.userId == self.currentUserId) {
return kickFirstMember(members.slice(1));
} else {
// Slight pause to avoid rate limiting.
return sleep(0.1)
.then(() => this.matrixClient.kick(roomId, member.userId, "Room Deleted"))
.catch((error) => {
if (error && error.errcode == "M_LIMIT_EXCEEDED") {
var retry = 1000;
if (error.data) {
const retryIn = error.data.retry_after_ms;
retry = Math.max(retry, retryIn ? retryIn : 0);
}
//console.log("Rate limited, retry in", retry);
return sleep(retry).then(() => kickFirstMember(members));
}
})
.finally(() => kickFirstMember(members.slice(1)))
}
};
return kickFirstMember(allMembers);
}) })
.then(() => { .then(() => {
statusCallback(null); statusCallback(null);
this.matrixClient.setGlobalErrorOnUnknownDevices( this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting);
oldGlobalErrorSetting
);
return this.leaveRoom(roomId); return this.leaveRoom(roomId);
}) })
.then(() => { .then(() => {
@ -734,9 +672,7 @@ export default {
}) })
.catch((err) => { .catch((err) => {
console.error("Error purging room", err); console.error("Error purging room", err);
this.matrixClient.setGlobalErrorOnUnknownDevices( this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting);
oldGlobalErrorSetting
);
reject(err); reject(err);
}); });
}); });
@ -814,10 +750,7 @@ export default {
* @param {*} userId * @param {*} userId
*/ */
isDirectRoomWith(room, userId) { isDirectRoomWith(room, userId) {
if ( if (room.getJoinRule() == "invite" && room.getMembers().length == 2) {
room.getJoinRule() == "invite" &&
room.getMembers().length == 2
) {
let other = room.getMember(userId); let other = room.getMember(userId);
if (other) { if (other) {
if (room.getMyMembership() == "invite" && other.membership == "join") { if (room.getMyMembership() == "invite" && other.membership == "join") {
@ -889,9 +822,7 @@ export default {
return this.matrixClient; return this.matrixClient;
}); });
} else { } else {
const tempMatrixClient = sdk.createClient( const tempMatrixClient = sdk.createClient(this.$config.defaultServer);
this.$config.defaultServer
);
var tempUserString = this.$store.state.tempuser; var tempUserString = this.$store.state.tempuser;
var tempUser = null; var tempUser = null;
if (tempUserString) { if (tempUserString) {
@ -971,13 +902,7 @@ export default {
}) })
.then((response) => { .then((response) => {
if (response.avatar_url) { if (response.avatar_url) {
response.avatar = matrixClient.mxcUrlToHttp( response.avatar = matrixClient.mxcUrlToHttp(response.avatar_url, 80, 80, "scale", true);
response.avatar_url,
80,
80,
"scale",
true
);
} }
return Promise.resolve(response); return Promise.resolve(response);
}) })
@ -1006,13 +931,7 @@ export default {
(roomId.startsWith("!") && room.room_id == roomId) (roomId.startsWith("!") && room.room_id == roomId)
) { ) {
if (room.avatar_url) { if (room.avatar_url) {
room.avatar = client.mxcUrlToHttp( room.avatar = client.mxcUrlToHttp(room.avatar_url, 80, 80, "scale", true);
room.avatar_url,
80,
80,
"scale",
true
);
} }
return Promise.resolve(room); return Promise.resolve(room);
} }
@ -1059,9 +978,7 @@ export default {
}, },
}); });
sdk.setCryptoStoreFactory( sdk.setCryptoStoreFactory(matrixService.createCryptoStore.bind(matrixService));
matrixService.createCryptoStore.bind(matrixService)
);
Vue.prototype.$matrix = matrixService; Vue.prototype.$matrix = matrixService;
}, },