Remove dead & duplicated code (#11405)

* Remove dead code

* Make dead code happier

* DRY pickle additional data calculation

* Iterate
This commit is contained in:
Michael Telatynski 2023-08-15 09:43:15 +01:00 committed by GitHub
parent 672ad98ec7
commit 27d79458da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 50 additions and 201 deletions

View file

@ -281,16 +281,15 @@ export default class AddThreepid {
): Promise<[success?: boolean, result?: IAuthData | Error | null] | undefined> { ): Promise<[success?: boolean, result?: IAuthData | Error | null] | undefined> {
const authClient = new IdentityAuthClient(); const authClient = new IdentityAuthClient();
let result: { success: boolean } | MatrixError;
if (this.submitUrl) { if (this.submitUrl) {
result = await this.matrixClient.submitMsisdnTokenOtherUrl( await this.matrixClient.submitMsisdnTokenOtherUrl(
this.submitUrl, this.submitUrl,
this.sessionId!, this.sessionId!,
this.clientSecret, this.clientSecret,
msisdnToken, msisdnToken,
); );
} else if (this.bind) { } else if (this.bind) {
result = await this.matrixClient.submitMsisdnToken( await this.matrixClient.submitMsisdnToken(
this.sessionId!, this.sessionId!,
this.clientSecret, this.clientSecret,
msisdnToken, msisdnToken,
@ -299,9 +298,6 @@ export default class AddThreepid {
} else { } else {
throw new UserFriendlyError("The add / bind with MSISDN flow is misconfigured"); throw new UserFriendlyError("The add / bind with MSISDN flow is misconfigured");
} }
if (result instanceof Error) {
throw result;
}
if (this.bind) { if (this.bind) {
await this.matrixClient.bindThreePid({ await this.matrixClient.bindThreePid({

View file

@ -67,7 +67,7 @@ export default abstract class BasePlatform {
protected notificationCount = 0; protected notificationCount = 0;
protected errorDidOccur = false; protected errorDidOccur = false;
public constructor() { protected constructor() {
dis.register(this.onAction); dis.register(this.onAction);
this.startUpdateCheck = this.startUpdateCheck.bind(this); this.startUpdateCheck = this.startUpdateCheck.bind(this);
} }
@ -365,14 +365,7 @@ export default abstract class BasePlatform {
return null; return null;
} }
const additionalData = new Uint8Array(userId.length + deviceId.length + 1); const additionalData = this.getPickleAdditionalData(userId, deviceId);
for (let i = 0; i < userId.length; i++) {
additionalData[i] = userId.charCodeAt(i);
}
additionalData[userId.length] = 124; // "|"
for (let i = 0; i < deviceId.length; i++) {
additionalData[userId.length + 1 + i] = deviceId.charCodeAt(i);
}
try { try {
const key = await crypto.subtle.decrypt( const key = await crypto.subtle.decrypt(
@ -387,6 +380,18 @@ export default abstract class BasePlatform {
} }
} }
private getPickleAdditionalData(userId: string, deviceId: string): Uint8Array {
const additionalData = new Uint8Array(userId.length + deviceId.length + 1);
for (let i = 0; i < userId.length; i++) {
additionalData[i] = userId.charCodeAt(i);
}
additionalData[userId.length] = 124; // "|"
for (let i = 0; i < deviceId.length; i++) {
additionalData[userId.length + 1 + i] = deviceId.charCodeAt(i);
}
return additionalData;
}
/** /**
* Create and store a pickle key for encrypting libolm objects. * Create and store a pickle key for encrypting libolm objects.
* @param {string} userId the user ID for the user that the pickle key is for. * @param {string} userId the user ID for the user that the pickle key is for.
@ -408,15 +413,7 @@ export default abstract class BasePlatform {
const iv = new Uint8Array(32); const iv = new Uint8Array(32);
crypto.getRandomValues(iv); crypto.getRandomValues(iv);
const additionalData = new Uint8Array(userId.length + deviceId.length + 1); const additionalData = this.getPickleAdditionalData(userId, deviceId);
for (let i = 0; i < userId.length; i++) {
additionalData[i] = userId.charCodeAt(i);
}
additionalData[userId.length] = 124; // "|"
for (let i = 0; i < deviceId.length; i++) {
additionalData[userId.length + 1 + i] = deviceId.charCodeAt(i);
}
const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv, additionalData }, cryptoKey, randomArray); const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv, additionalData }, cryptoKey, randomArray);
try { try {

View file

@ -75,10 +75,6 @@ export default class IdentityAuthClient {
return window.localStorage.getItem("mx_is_access_token"); return window.localStorage.getItem("mx_is_access_token");
} }
public hasCredentials(): boolean {
return Boolean(this.accessToken);
}
// Returns a promise that resolves to the access_token string from the IS // Returns a promise that resolves to the access_token string from the IS
public async getAccessToken({ check = true } = {}): Promise<string | null> { public async getAccessToken({ check = true } = {}): Promise<string | null> {
if (!this.authEnabled) { if (!this.authEnabled) {

View file

@ -429,15 +429,6 @@ export default class LegacyCallHandler extends EventEmitter {
return this.calls.get(roomId) || null; return this.calls.get(roomId) || null;
} }
public getAnyActiveCall(): MatrixCall | null {
for (const call of this.calls.values()) {
if (call.state !== CallState.Ended) {
return call;
}
}
return null;
}
public getAllActiveCalls(): MatrixCall[] { public getAllActiveCalls(): MatrixCall[] {
const activeCalls: MatrixCall[] = []; const activeCalls: MatrixCall[] = [];

View file

@ -47,41 +47,6 @@ export default class PasswordReset {
this.clientSecret = this.client.generateClientSecret(); this.clientSecret = this.client.generateClientSecret();
} }
/**
* Attempt to reset the user's password. This will trigger a side-effect of
* sending an email to the provided email address.
* @param {string} emailAddress The email address
* @param {string} newPassword The new password for the account.
* @param {boolean} logoutDevices Should all devices be signed out after the reset? Defaults to `true`.
* @return {Promise} Resolves when the email has been sent. Then call checkEmailLinkClicked().
*/
public async resetPassword(
emailAddress: string,
newPassword: string,
logoutDevices = true,
): Promise<IRequestTokenResponse> {
this.password = newPassword;
this.logoutDevices = logoutDevices;
this.sendAttempt++;
try {
const result = await this.client.requestPasswordEmailToken(
emailAddress,
this.clientSecret,
this.sendAttempt,
);
this.sessionId = result.sid;
return result;
} catch (err: any) {
if (err.errcode === "M_THREEPID_NOT_FOUND") {
err.message = _t("This email address was not found");
} else if (err.httpStatus) {
err.message = err.message + ` (Status ${err.httpStatus})`;
}
throw err;
}
}
/** /**
* Request a password reset token. * Request a password reset token.
* This will trigger a side-effect of sending an email to the provided email address. * This will trigger a side-effect of sending an email to the provided email address.

View file

@ -256,9 +256,8 @@ export function determineUnreadState(
return { symbol: null, count: trueCount, color: NotificationColor.Grey }; return { symbol: null, count: trueCount, color: NotificationColor.Grey };
} }
// We don't have any notified messages, but we might have unread messages. Let's // We don't have any notified messages, but we might have unread messages. Let's find out.
// find out. let hasUnread: boolean;
let hasUnread = false;
if (threadId) hasUnread = doesRoomOrThreadHaveUnreadMessages(room.getThread(threadId)!); if (threadId) hasUnread = doesRoomOrThreadHaveUnreadMessages(room.getThread(threadId)!);
else hasUnread = doesRoomHaveUnreadMessages(room); else hasUnread = doesRoomHaveUnreadMessages(room);

View file

@ -679,7 +679,7 @@ function canSendEvent(event: MessageEvent<any>, roomId: string): void {
} }
const me = client.credentials.userId!; const me = client.credentials.userId!;
let canSend = false; let canSend: boolean;
if (isState) { if (isState) {
canSend = room.currentState.maySendStateEvent(evType, me); canSend = room.currentState.maySendStateEvent(evType, me);
} else { } else {

View file

@ -117,7 +117,7 @@ const FeedbackDialog: React.FC<IProps> = (props: IProps) => {
return ( return (
<QuestionDialog <QuestionDialog
className="mx_FeedbackDialog" className="mx_FeedbackDialog"
hasCancelButton={!!hasFeedback} hasCancelButton={hasFeedback}
title={_t("Feedback")} title={_t("Feedback")}
description={ description={
<React.Fragment> <React.Fragment>

View file

@ -461,7 +461,7 @@ export default class EditorModel {
*/ */
public transform(callback: ManualTransformCallback): Promise<void> { public transform(callback: ManualTransformCallback): Promise<void> {
const pos = callback(); const pos = callback();
let acPromise: Promise<void> | null = null; let acPromise: Promise<void> | null;
if (!(pos instanceof Range)) { if (!(pos instanceof Range)) {
acPromise = this.setActivePart(pos, true); acPromise = this.setActivePart(pos, true);
} else { } else {

View file

@ -112,13 +112,6 @@ export default abstract class BaseEventIndexManager {
throw new Error("Unimplemented"); throw new Error("Unimplemented");
} }
/**
* Check if our event index is empty.
*/
public indexIsEmpty(): Promise<boolean> {
throw new Error("Unimplemented");
}
/** /**
* Check if the room with the given id is already indexed. * Check if the room with the given id is already indexed.
* *

View file

@ -26,7 +26,6 @@ import IntegrationsImpossibleDialog from "../components/views/dialogs/Integratio
import IntegrationsDisabledDialog from "../components/views/dialogs/IntegrationsDisabledDialog"; import IntegrationsDisabledDialog from "../components/views/dialogs/IntegrationsDisabledDialog";
import WidgetUtils from "../utils/WidgetUtils"; import WidgetUtils from "../utils/WidgetUtils";
import { MatrixClientPeg } from "../MatrixClientPeg"; import { MatrixClientPeg } from "../MatrixClientPeg";
import { parseUrl } from "../utils/UrlUtils";
const KIND_PREFERENCE = [ const KIND_PREFERENCE = [
// Ordered: first is most preferred, last is least preferred. // Ordered: first is most preferred, last is least preferred.
@ -179,52 +178,6 @@ export class IntegrationManagers {
public showDisabledDialog(): void { public showDisabledDialog(): void {
Modal.createDialog(IntegrationsDisabledDialog); Modal.createDialog(IntegrationsDisabledDialog);
} }
/**
* Attempts to discover an integration manager using only its name. This will not validate that
* the integration manager is functional - that is the caller's responsibility.
* @param {string} domainName The domain name to look up.
* @returns {Promise<IntegrationManagerInstance>} Resolves to an integration manager instance,
* or null if none was found.
*/
public async tryDiscoverManager(domainName: string): Promise<IntegrationManagerInstance | null> {
logger.log("Looking up integration manager via .well-known");
if (domainName.startsWith("http:") || domainName.startsWith("https:")) {
// trim off the scheme and just use the domain
domainName = parseUrl(domainName).host;
}
let wkConfig: IClientWellKnown;
try {
const result = await fetch(`https://${domainName}/.well-known/matrix/integrations`);
wkConfig = await result.json();
} catch (e) {
logger.error(e);
logger.warn("Failed to locate integration manager");
return null;
}
if (!wkConfig || !wkConfig["m.integrations_widget"]) {
logger.warn("Missing integrations widget on .well-known response");
return null;
}
const widget = wkConfig["m.integrations_widget"];
if (!widget["url"] || !widget["data"] || !widget["data"]["api_url"]) {
logger.warn("Malformed .well-known response for integrations widget");
return null;
}
// All discovered managers are per-user managers
const manager = new IntegrationManagerInstance(Kind.Account, widget["data"]["api_url"], widget["url"]);
logger.log("Got an integration manager (untested)");
// We don't test the manager because the caller may need to do extra
// checks or similar with it. For instance, they may need to deal with
// terms of service or want to call something particular.
return manager;
}
} }
// For debugging // For debugging

View file

@ -63,10 +63,6 @@ export class BanList {
return this._rules.filter((r) => r.kind === RULE_USER); return this._rules.filter((r) => r.kind === RULE_USER);
} }
public get roomRules(): ListRule[] {
return this._rules.filter((r) => r.kind === RULE_ROOM);
}
public async banEntity(kind: string, entity: string, reason: string): Promise<any> { public async banEntity(kind: string, entity: string, reason: string): Promise<any> {
const type = ruleTypeToStable(kind); const type = ruleTypeToStable(kind);
if (!type) return; // unknown rule type if (!type) return; // unknown rule type

View file

@ -157,7 +157,7 @@ export abstract class Call extends TypedEventEmitter<CallEvent, CallEventHandler
this.emit(CallEvent.Participants, value, prevValue); this.emit(CallEvent.Participants, value, prevValue);
} }
public constructor( protected constructor(
/** /**
* The widget used to access this call. * The widget used to access this call.
*/ */

View file

@ -117,7 +117,7 @@ async function collectBugReport(opts: IOpts = {}, gzipLogs = true): Promise<Form
); );
body.append("secret_storage_ready", String(await client.isSecretStorageReady())); body.append("secret_storage_ready", String(await client.isSecretStorageReady()));
body.append("secret_storage_key_in_account", String(!!(await secretStorage.hasKey()))); body.append("secret_storage_key_in_account", String(await secretStorage.hasKey()));
body.append("session_backup_key_in_secret_storage", String(!!(await client.isKeyBackupKeyStored()))); body.append("session_backup_key_in_secret_storage", String(!!(await client.isKeyBackupKeyStored())));
const sessionBackupKeyFromCache = await client.crypto.getSessionBackupPrivateKey(); const sessionBackupKeyFromCache = await client.crypto.getSessionBackupPrivateKey();

View file

@ -139,7 +139,7 @@ async function getCryptoContext(client: MatrixClient): Promise<CryptoContext> {
!!(pkCache && (await pkCache.getCrossSigningKeyCache?.("user_signing"))), !!(pkCache && (await pkCache.getCrossSigningKeyCache?.("user_signing"))),
), ),
secret_storage_ready: String(await client.isSecretStorageReady()), secret_storage_ready: String(await client.isSecretStorageReady()),
secret_storage_key_in_account: String(!!(await secretStorage.hasKey())), secret_storage_key_in_account: String(await secretStorage.hasKey()),
session_backup_key_in_secret_storage: String(!!(await client.isKeyBackupKeyStored())), session_backup_key_in_secret_storage: String(!!(await client.isKeyBackupKeyStored())),
session_backup_key_cached: String(!!sessionBackupKeyFromCache), session_backup_key_cached: String(!!sessionBackupKeyFromCache),
session_backup_key_well_formed: String(sessionBackupKeyFromCache instanceof Uint8Array), session_backup_key_well_formed: String(sessionBackupKeyFromCache instanceof Uint8Array),

View file

@ -577,10 +577,9 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> implements
* @param {IFilterCondition} filter The filter condition to add. * @param {IFilterCondition} filter The filter condition to add.
*/ */
public async addFilter(filter: IFilterCondition): Promise<void> { public async addFilter(filter: IFilterCondition): Promise<void> {
let promise = Promise.resolve();
filter.on(FILTER_CHANGED, this.onPrefilterUpdated); filter.on(FILTER_CHANGED, this.onPrefilterUpdated);
this.prefilterConditions.push(filter); this.prefilterConditions.push(filter);
promise = this.recalculatePrefiltering(); const promise = this.recalculatePrefiltering();
promise.then(() => this.updateFn.trigger()); promise.then(() => this.updateFn.trigger());
} }

View file

@ -399,6 +399,4 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
} }
protected async onAction(payload: ActionPayload): Promise<void> {} protected async onAction(payload: ActionPayload): Promise<void> {}
protected async onDispatchAsync(payload: ActionPayload): Promise<void> {}
} }

View file

@ -90,10 +90,6 @@ export class Algorithm extends EventEmitter {
return this._stickyRoom ? this._stickyRoom.room : null; return this._stickyRoom ? this._stickyRoom.room : null;
} }
public get knownRooms(): Room[] {
return this.rooms;
}
public get hasTagSortingMap(): boolean { public get hasTagSortingMap(): boolean {
return !!this.sortAlgorithms; return !!this.sortAlgorithms;
} }

View file

@ -242,10 +242,6 @@ export class StopGapWidget extends EventEmitter {
return parsed.toString().replace(/%24/g, "$"); return parsed.toString().replace(/%24/g, "$");
} }
public get isManagedByManager(): boolean {
return !!this.scalarToken;
}
public get started(): boolean { public get started(): boolean {
return !!this.messaging; return !!this.messaging;
} }

View file

@ -245,7 +245,7 @@ export class StopGapWidgetDriver extends WidgetDriver {
if (!client || !roomId) throw new Error("Not in a room or not attached to a client"); if (!client || !roomId) throw new Error("Not in a room or not attached to a client");
let r: { event_id: string } | null = null; // eslint-disable-line camelcase let r: { event_id: string } | null;
if (stateKey !== null) { if (stateKey !== null) {
// state event // state event
r = await client.sendStateEvent(roomId, eventType, content, stateKey); r = await client.sendStateEvent(roomId, eventType, content, stateKey);

View file

@ -411,45 +411,6 @@ export default class WidgetUtils {
return widgets.filter((w) => w.content?.type === "m.integration_manager"); return widgets.filter((w) => w.content?.type === "m.integration_manager");
} }
public static getRoomWidgetsOfType(room: Room, type: WidgetType): MatrixEvent[] {
const widgets = WidgetUtils.getRoomWidgets(room) || [];
return widgets.filter((w) => {
const content = w.getContent();
return content.url && type.matches(content.type);
});
}
public static async removeIntegrationManagerWidgets(client: MatrixClient | undefined): Promise<void> {
if (!client) {
throw new Error("User not logged in");
}
const widgets = client.getAccountData("m.widgets");
if (!widgets) return;
const userWidgets: Record<string, IWidgetEvent> = widgets.getContent() || {};
Object.entries(userWidgets).forEach(([key, widget]) => {
if (widget.content && widget.content.type === "m.integration_manager") {
delete userWidgets[key];
}
});
await client.setAccountData("m.widgets", userWidgets);
}
public static addIntegrationManagerWidget(
client: MatrixClient,
name: string,
uiUrl: string,
apiUrl: string,
): Promise<void> {
return WidgetUtils.setUserWidget(
client,
"integration_manager_" + new Date().getTime(),
WidgetType.INTEGRATION_MANAGER,
uiUrl,
"Integration manager: " + name,
{ api_url: apiUrl },
);
}
/** /**
* Remove all stickerpicker widgets (stickerpickers are user widgets by nature) * Remove all stickerpicker widgets (stickerpickers are user widgets by nature)
* @param client The matrix client of the logged-in user * @param client The matrix client of the logged-in user

View file

@ -69,8 +69,4 @@ export class PermalinkParts {
public get primaryEntityId(): string | null { public get primaryEntityId(): string | null {
return this.roomIdOrAlias || this.userId; return this.roomIdOrAlias || this.userId;
} }
public get sigil(): string {
return this.primaryEntityId?.[0] || "?";
}
} }

View file

@ -114,6 +114,7 @@ export class RoomPermalinkCreator {
} }
public start(): void { public start(): void {
if (this.started) return;
this.load(); this.load();
this.room?.currentState.on(RoomStateEvent.Update, this.onRoomStateUpdate); this.room?.currentState.on(RoomStateEvent.Update, this.onRoomStateUpdate);
this.started = true; this.started = true;
@ -128,10 +129,6 @@ export class RoomPermalinkCreator {
return this._serverCandidates; return this._serverCandidates;
} }
public isStarted(): boolean {
return this.started;
}
public forEvent(eventId: string): string { public forEvent(eventId: string): string {
return getPermalinkConstructor().forEvent(this.roomId, eventId, this._serverCandidates); return getPermalinkConstructor().forEvent(this.roomId, eventId, this._serverCandidates);
} }

View file

@ -31,7 +31,6 @@ describe("transforming search term", () => {
eventId: "", eventId: "",
userId: "", userId: "",
viaServers: [], viaServers: [],
sigil: "",
}); });
expect(transformSearchTerm(roomLink)).toBe(parsedPermalink); expect(transformSearchTerm(roomLink)).toBe(parsedPermalink);
@ -46,7 +45,6 @@ describe("transforming search term", () => {
eventId: null, eventId: null,
userId: null, userId: null,
viaServers: null, viaServers: null,
sigil: "?",
}); });
expect(transformSearchTerm(searchTerm)).toBe(searchTerm); expect(transformSearchTerm(searchTerm)).toBe(searchTerm);

View file

@ -12,6 +12,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { EventEmitter } from "events";
import { Room, RoomMember, EventType, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { Room, RoomMember, EventType, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from "../../../src/MatrixClientPeg"; import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
@ -87,6 +89,26 @@ describe("Permalinks", function () {
jest.spyOn(MatrixClientPeg, "get").mockRestore(); jest.spyOn(MatrixClientPeg, "get").mockRestore();
}); });
it("should not clean up listeners even if start was called multiple times", () => {
const room = mockRoom("!fake:example.org", []);
const getListenerCount = (emitter: EventEmitter) =>
emitter
.eventNames()
.map((e) => emitter.listenerCount(e))
.reduce((a, b) => a + b, 0);
const listenerCountBefore = getListenerCount(room.currentState);
const creator = new RoomPermalinkCreator(room);
creator.start();
creator.start();
creator.start();
creator.start();
expect(getListenerCount(room.currentState)).toBeGreaterThan(listenerCountBefore);
creator.stop();
expect(getListenerCount(room.currentState)).toBe(listenerCountBefore);
});
it("should pick no candidate servers when the room has no members", function () { it("should pick no candidate servers when the room has no members", function () {
const room = mockRoom("!fake:example.org", []); const room = mockRoom("!fake:example.org", []);
const creator = new RoomPermalinkCreator(room); const creator = new RoomPermalinkCreator(room);