fix double-requests by removing verify on connect

This commit is contained in:
Michael Peters 2022-10-25 22:37:40 -07:00
parent aa90edb142
commit 366022cebb
7 changed files with 26 additions and 30 deletions

View File

@ -5,7 +5,6 @@ const LOG = Logger.create(__filename, electronConsole);
import { Changes, WithEquals } from './data-types';
import * as uuid from 'uuid';
import assert from 'assert';
export enum AutoVerifierChangesType {
@ -30,8 +29,6 @@ export class AutoVerifier<T> {
private verifyPromise: Promise<boolean> | null = null;
public trustedStatus: 'none' | 'fetching' | 'verifying' | 'verified' = 'none';
private verifierId: string;
/**
* allows a trusted function to verify the primary function
* @param primaryFunc The primary function
@ -42,9 +39,8 @@ export class AutoVerifier<T> {
private primaryFunc: () => Promise<T | null>,
private trustedFunc: () => Promise<T | null>,
private verifyFunc: (primaryResult: T | null, trustedResult: T | null) => Promise<boolean>,
) {
this.verifierId = uuid.v4().slice(undefined, 4);
}
private name: string | null = null, // for debugging
) {}
/** returns the changes that must be made to primaryResult given trustedResult */
static getChanges<T extends WithEquals<T> & { id: string }>(
@ -125,6 +121,7 @@ export class AutoVerifier<T> {
primaryFunc: () => Promise<T[] | null>,
trustedFunc: () => Promise<T[] | null>,
changesFunc: (changesType: AutoVerifierChangesType, changes: Changes<T>) => Promise<boolean>,
name: string | null = null,
) {
return new AutoVerifier<T[]>(
primaryFunc,
@ -134,6 +131,7 @@ export class AutoVerifier<T> {
const changesType = AutoVerifier.getListChangesType<T>(primaryResult, trustedResult, changes);
return await changesFunc(changesType, changes);
},
name,
);
}
@ -145,6 +143,7 @@ export class AutoVerifier<T> {
primaryResult: T | null,
trustedResult: T | null,
) => Promise<boolean>,
name: string | null = null,
) {
return new AutoVerifier<T>(
primaryFunc,
@ -153,6 +152,7 @@ export class AutoVerifier<T> {
const changesType = AutoVerifier.getSingleChangesType<T>(primaryResult, trustedResult);
return await changesFunc(changesType, primaryResult, trustedResult);
},
name,
);
}

View File

@ -55,6 +55,7 @@ const ChannelElement: FC<ChannelElementProps> = (props: ChannelElementProps) =>
setOverlay(<ChannelOverlay channel={channel} />);
}, [setOverlay, channel]);
// TODO: Restrict for permissions
return (
<div className={baseClassName} onClick={setSelfActiveChannel}>
<div className="icon">{BaseElements.TEXT_CHANNEL_ICON}</div>

View File

@ -22,7 +22,7 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
public readonly fetchMessagesBeforeVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>;
public readonly fetchMessagesAfterVerifier: AutoVerifierWithArg<Message[], PartialMessageListQuery>;
constructor(private primary: Fetchable & Lackable, private trusted: Fetchable & Ensurable) {
constructor(private primary: Fetchable & Lackable, private trusted: Fetchable & Ensurable, private name: string | null = null) {
super();
if (trusted instanceof PairVerifierFetchable) {
@ -239,7 +239,6 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
}
unverify() {
// lOG.debug('unverifying all');
this.fetchMetadataVerifier.unverify();
this.fetchMembersVerifier.unverify();
this.fetchChannelsVerifier.unverify();
@ -250,10 +249,6 @@ export default class PairVerifierFetchable extends EventEmitter<Conflictable> im
this.fetchMessagesRecentVerifier.unverifyAll();
this.fetchMessagesBeforeVerifier.unverifyAll();
this.fetchMessagesAfterVerifier.unverifyAll();
if (this.trusted instanceof PairVerifierFetchable) {
this.trusted.unverify();
}
}
async fetchMetadata(): Promise<GuildMetadata | null> {

View File

@ -59,14 +59,15 @@ export default class CombinedGuild
this.personalDBGuild = new PersonalDBGuild(personalDB, this.id, this.memberId);
this.socketGuild = new SocketGuild(socket, socketVerifier);
const diskSocket = new PairVerifierFetchable(this.personalDBGuild, this.socketGuild);
const ramDiskSocket = new PairVerifierFetchable(this.ramGuild, diskSocket);
const diskSocket = new PairVerifierFetchable(this.personalDBGuild, this.socketGuild, 'Disk -> Socket');
const ramDiskSocket = new PairVerifierFetchable(this.ramGuild, diskSocket, 'RAM -> Disk');
// TODO: I think this unverify is causing the RARE ALERTs
// do we need to unverify on connect? or just disconnect?
// connect/Disconnect
this.socketGuild.on('connect', () => {
LOG.info(`g#${this.id} connected`);
diskSocket.unverify();
ramDiskSocket.unverify();
ramDiskSocket.unverify(); // make sure to query the disk-socket AutoVerifier again
this.emit('connect');
});
this.socketGuild.on('disconnect', async () => {

View File

@ -53,7 +53,7 @@ export default class SocketVerifier extends EventEmitter<{ verified: () => void
}
this.memberId = memberId;
this.isVerified = true;
LOG.debug(`verified as u#${memberId}`);
LOG.debug(`verified as u#${memberId.slice(0, 4)}`);
resolve(memberId);
this.emit('verified');
});

View File

@ -67,7 +67,7 @@ export default class DB {
// eslint-disable-next-line newline-per-chained-call
LOG.silly(
`searching for public key (der hash: ${LOG.inspect(
crypto.createHash('sha256').update(der).digest().toString('hex'),
crypto.createHash('sha256').update(der).digest().toString('hex').slice(0, 8),
)})`,
);

View File

@ -127,7 +127,6 @@ function bindEvent(
}
}
}
//lOG.debug(`c#${client.id}: ${name}`);
try {
await handler(...args);
} catch (e) {
@ -139,7 +138,7 @@ function bindEvent(
}
} catch (e) {
if (e instanceof SignatureError) {
LOG.warn(`c#${client.id}: ${name} request does not match expected signature`, {
LOG.warn(`c#${client.id.slice(0, 4)}: ${name} request does not match expected signature`, {
signature,
args,
msg: e.message,
@ -147,7 +146,7 @@ function bindEvent(
// do not respond to requests with invalid signatures
} else if (e instanceof EventError) {
LOG.warn(
`c#${client.id}: ${e.message}${e.extended_message ? ' / ' + e.extended_message : ''}`,
`c#${client.id.slice(0, 4)}: ${e.message}${e.extended_message ? ' / ' + e.extended_message : ''}`,
e.cause,
);
respond(e.message);
@ -204,7 +203,7 @@ function bindRegistrationEvents(io: socketio.Server, client: socketio.Socket): v
const member = await DB.getMember(guildId, memberId);
const meta = await DB.getGuild(guildId);
LOG.info(`c#${client.id}: registered with t#${token} as u#${member.id} / ${member.display_name}`);
LOG.info(`c#${client.id.slice(0, 4)}: registered with t#${token} as u#${member.id} / ${member.display_name}`);
respond(null, member, meta);
@ -245,7 +244,7 @@ function bindChallengeVerificationEvents(io: socketio.Server, client: socketio.S
throw new EventError('unauthorized public key', e as Error);
}
LOG.debug(`c#${client.id}: challenging for u#${identity.memberId?.slice(0, 4)}`);
LOG.debug(`c#${client.id.slice(0, 4)}: challenging for u#${identity.memberId?.slice(0, 4)}`);
if (connected.find(i => i.memberId === identity.memberId && i.verified)) {
throw new EventError('member already connected');
@ -315,10 +314,10 @@ function bindChallengeVerificationEvents(io: socketio.Server, client: socketio.S
.map((privilege: string) => guildPrivilegeRoomName(identity.guildId as string, privilege))
: [],
);
LOG.debug(`c#${client.id} joining ${rooms.join(', ')}`);
LOG.debug(`c#${client.id.slice(0, 4)} joining g#[${rooms.map(room => room.slice(0, 4)).join(', ')}]`);
client.join(rooms);
LOG.info(`c#${client.id}: verified as g#${identity.guildId} u#${identity.memberId?.slice(0, 4)}`);
LOG.info(`c#${client.id.slice(0, 4)}: verified as g#${identity.guildId.slice(0, 4)} u#${identity.memberId?.slice(0, 4)}`);
respond(null, identity.memberId);
});
}
@ -753,7 +752,7 @@ function bindActionEvents(io: socketio.Server, client: socketio.Socket, identity
if (!identity.memberId) throw new EventError('identity no memberId');
if (avatarBuff.length > MAX_AVATAR_SIZE) {
LOG.warn(`c#${client.id}: avatar too large`);
LOG.warn(`c#${client.id.slice(0, 4)}: avatar too large`);
respond('buffer too large');
return;
}
@ -825,7 +824,7 @@ function bindFetchEvents(client: socketio.Socket, identity: IIdentity): void {
if (!identity.guildId) throw new EventError('identity no guildId');
if (!identity.memberId) throw new EventError('identity no memberId');
LOG.info(
`u#${identity.memberId?.slice(0, 4)}: fetching recent messages for ch#${channelId} number: ${number}`,
`u#${identity.memberId?.slice(0, 4)}: fetching recent messages for ch#${channelId.slice(0, 4)} number: ${number}`,
);
const messages = await DB.getMessagesRecent(identity.guildId, channelId, number);
respond(null, messages);
@ -929,7 +928,7 @@ function bindFetchEvents(client: socketio.Socket, identity: IIdentity): void {
export function bindSocketEvents(io: socketio.Server): void {
io.on('connection', client => {
LOG.info(`c#${client.id}: connected`);
LOG.info(`c#${client.id.slice(0, 4)}: connected`);
const identity: IIdentity = {
guildId: null,
@ -953,7 +952,7 @@ export function bindSocketEvents(io: socketio.Server): void {
1,
);
if (identity.verified) {
LOG.info(`c#${client.id}: disconnected (was u#${identity.memberId?.slice(0, 4)})`);
LOG.info(`c#${client.id.slice(0, 4)}: disconnected (was u#${identity.memberId?.slice(0, 4)})`);
(async () => {
if (!identity.guildId || !identity.memberId) return;
try {
@ -963,7 +962,7 @@ export function bindSocketEvents(io: socketio.Server): void {
}
})();
} else {
LOG.info(`c#${client.id}: disconnected (was unverified)`);
LOG.info(`c#${client.id.slice(0, 4)}: disconnected (was unverified)`);
}
});
});