Add common utility for checking 3pid invites

We just need to make sure they are structurally sound - actual validation is done by other parties.
This commit is contained in:
Travis Ralston 2019-03-29 11:45:07 -06:00
parent 0258f61f63
commit 07cc640089
4 changed files with 26 additions and 9 deletions

View file

@ -65,6 +65,24 @@ export function showRoomInviteDialog(roomId) {
}); });
} }
/**
* Checks if the given MatrixEvent is a valid 3rd party user invite.
* @param {MatrixEvent} event The event to check
* @returns {boolean} True if valid, false otherwise
*/
export function isValid3pidInvite(event) {
if (!event || event.getType() !== "m.room.third_party_invite") return false;
// any events without these keys are not valid 3pid invites, so we ignore them
const requiredKeys = ['key_validity_url', 'public_key', 'display_name'];
for (let i = 0; i < requiredKeys.length; ++i) {
if (!event.getContent()[requiredKeys[i]]) return false;
}
// Valid enough by our standards
return true;
}
function _onStartChatFinished(shouldInvite, addrs) { function _onStartChatFinished(shouldInvite, addrs) {
if (!shouldInvite) return; if (!shouldInvite) return;

View file

@ -17,6 +17,7 @@ import MatrixClientPeg from './MatrixClientPeg';
import CallHandler from './CallHandler'; import CallHandler from './CallHandler';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import * as Roles from './Roles'; import * as Roles from './Roles';
import {isValid3pidInvite} from "./RoomInvite";
function textForMemberEvent(ev) { function textForMemberEvent(ev) {
// XXX: SYJS-16 "sender is sometimes null for join messages" // XXX: SYJS-16 "sender is sometimes null for join messages"
@ -367,7 +368,7 @@ function textForCallInviteEvent(event) {
function textForThreePidInviteEvent(event) { function textForThreePidInviteEvent(event) {
const senderName = event.sender ? event.sender.name : event.getSender(); const senderName = event.sender ? event.sender.name : event.getSender();
if (!event.getContent().display_name) { if (!isValid3pidInvite(event)) {
const targetDisplayName = event.getPrevContent().display_name || _t("Someone"); const targetDisplayName = event.getPrevContent().display_name || _t("Someone");
return _t('%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.', { return _t('%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.', {
senderName, senderName,

View file

@ -20,6 +20,7 @@ import React from 'react';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import SdkConfig from '../../../SdkConfig'; import SdkConfig from '../../../SdkConfig';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import {isValid3pidInvite} from "../../../RoomInvite";
const MatrixClientPeg = require("../../../MatrixClientPeg"); const MatrixClientPeg = require("../../../MatrixClientPeg");
const sdk = require('../../../index'); const sdk = require('../../../index');
const rate_limited_func = require('../../../ratelimitedfunc'); const rate_limited_func = require('../../../ratelimitedfunc');
@ -379,11 +380,7 @@ module.exports = React.createClass({
if (room) { if (room) {
return room.currentState.getStateEvents("m.room.third_party_invite").filter(function(e) { return room.currentState.getStateEvents("m.room.third_party_invite").filter(function(e) {
// any events without these keys are not valid 3pid invites, so we ignore them if (!isValid3pidInvite(e)) return false;
const requiredKeys = ['key_validity_url', 'public_key', 'display_name'];
for (let i = 0; i < requiredKeys.length; ++i) {
if (e.getContent()[requiredKeys[i]] === undefined) return false;
}
// discard all invites which have a m.room.member event since we've // discard all invites which have a m.room.member event since we've
// already added them. // already added them.

View file

@ -22,6 +22,7 @@ import {_t} from "../../../languageHandler";
import dis from "../../../dispatcher"; import dis from "../../../dispatcher";
import sdk from "../../../index"; import sdk from "../../../index";
import Modal from "../../../Modal"; import Modal from "../../../Modal";
import {isValid3pidInvite} from "../../../RoomInvite";
export default class ThirdPartyMemberInfo extends React.Component { export default class ThirdPartyMemberInfo extends React.Component {
static propTypes = { static propTypes = {
@ -64,7 +65,7 @@ export default class ThirdPartyMemberInfo extends React.Component {
onRoomStateEvents = (ev) => { onRoomStateEvents = (ev) => {
if (ev.getType() === "m.room.third_party_invite" && ev.getStateKey() === this.state.stateKey) { if (ev.getType() === "m.room.third_party_invite" && ev.getStateKey() === this.state.stateKey) {
const newDisplayName = ev.getContent().display_name; const newDisplayName = ev.getContent().display_name;
const isInvited = !!newDisplayName; // display_name indicates a valid invite const isInvited = isValid3pidInvite(ev);
const newState = {invited: isInvited}; const newState = {invited: isInvited};
if (newDisplayName) newState['displayName'] = newDisplayName; if (newDisplayName) newState['displayName'] = newDisplayName;
@ -123,8 +124,8 @@ export default class ThirdPartyMemberInfo extends React.Component {
<div className="mx_MemberInfo"> <div className="mx_MemberInfo">
<div className="mx_MemberInfo_name"> <div className="mx_MemberInfo_name">
<AccessibleButton className="mx_MemberInfo_cancel" <AccessibleButton className="mx_MemberInfo_cancel"
onClick={this.onCancel} onClick={this.onCancel}
title={_t('Close')} title={_t('Close')}
/> />
<h2>{this.state.displayName}</h2> <h2>{this.state.displayName}</h2>
</div> </div>