fix(guild): render activity log entries deterministically (#2766)

This commit is contained in:
Hampus Kraft committed 2026-09-14 17:39:19 +02:00
1 parent ed10f9d323
commit a3d6cf37cb
135 files changed
+75869 -2708

No files matched your search

@@ -129,12 +129,14 @@ export class ChannelOperationsService {
data,
clientFeatures,
requestCache,
auditLogReason,
}: {
userId: UserID;
channelId: ChannelID;
data: ChannelUpdateData;
clientFeatures: ReadonlySet<string>;
requestCache: RequestCache;
auditLogReason: string | null;
}): Promise<Channel> {
const {channel, guild, checkPermission} = await this.channelAuthService.getChannelAuthenticated({
userId,
@@ -339,7 +341,7 @@ export class ChannelOperationsService {
const builder = this.guildAuditLogService
.createBuilder(guildIdValue, userId)
.withAction(AuditLogActionType.CHANNEL_UPDATE, channel.id.toString())
.withReason(null)
.withReason(auditLogReason)
.withMetadata({
type: updatedChannel.type.toString(),
})
@@ -358,8 +360,6 @@ export class ChannelOperationsService {
'Failed to record guild audit log',
);
}
if (data.name !== undefined && channel.name !== updatedChannel.name) {
}
}
if (data.permission_overwrites !== undefined) {
await this.guildAuditLogService.recordPermissionOverwriteDiff({
@@ -368,6 +368,7 @@ export class ChannelOperationsService {
channelId: updatedChannel.id,
previous: previousPermissionOverwrites,
next: updatedChannel.permissionOverwrites,
reason: auditLogReason,
});
}
return updatedChannel;
@@ -377,10 +378,12 @@ export class ChannelOperationsService {
userId,
channelId,
requestCache,
auditLogReason,
}: {
userId: UserID;
channelId: ChannelID;
requestCache: RequestCache;
auditLogReason: string | null;
}): Promise<void> {
const {channel, guild, checkPermission} = await this.channelAuthService.getChannelAuthenticated({
userId,
@@ -421,7 +424,7 @@ export class ChannelOperationsService {
const builder = this.guildAuditLogService
.createBuilder(guildIdValue, userId)
.withAction(AuditLogActionType.CHANNEL_DELETE, channel.id.toString())
.withReason(null)
.withReason(auditLogReason)
.withMetadata({
type: channel.type.toString(),
})
@@ -611,6 +614,7 @@ export class ChannelOperationsService {
};
clientFeatures: ReadonlySet<string>;
requestCache: RequestCache;
auditLogReason: string | null;
}): Promise<void> {
const channel = await this.channelRepository.channelData.findUnique(params.channelId);
if (!channel || !channel.guildId) throw new UnknownChannelError();
@@ -646,15 +650,13 @@ export class ChannelOperationsService {
const removedDeny = (existing?.deny ?? 0n) & ~sanitizedDeny;
if (!hasAdministrator && (removedDeny & ~userPermissions) !== 0n) throw new MissingPermissionsError();
const previousPermissionOverwrites = channel.permissionOverwrites;
const nextOverwrite = new ChannelPermissionOverwrite({
type: params.overwrite.type,
allow_: sanitizedAllow,
deny_: sanitizedDeny,
});
const overwrites = new Map(channel.permissionOverwrites ?? []);
overwrites.set(
targetId,
new ChannelPermissionOverwrite({
type: params.overwrite.type,
allow_: sanitizedAllow,
deny_: sanitizedDeny,
}),
);
overwrites.set(targetId, nextOverwrite);
const updated = await this.channelRepository.channelData.upsert({
...channel.toRow(),
permission_overwrites: new Map(
@@ -670,50 +672,14 @@ export class ChannelOperationsService {
requestCache: params.requestCache,
});
}
const previousSnapshot = existing
? {
id: params.overwriteId.toString(),
type: existing.type.toString(),
allow: existing.allow.toString(),
deny: existing.deny.toString(),
}
: null;
const nextSnapshot = {
id: params.overwriteId.toString(),
type: params.overwrite.type.toString(),
allow: sanitizedAllow.toString(),
deny: sanitizedDeny.toString(),
};
const changes = this.guildAuditLogService.computeChanges(previousSnapshot, nextSnapshot);
if (changes.length > 0) {
const action = existing
? AuditLogActionType.CHANNEL_OVERWRITE_UPDATE
: AuditLogActionType.CHANNEL_OVERWRITE_CREATE;
const builder = this.guildAuditLogService
.createBuilder(channel.guildId, params.userId)
.withAction(action, params.overwriteId.toString())
.withReason(null)
.withMetadata({
id: params.overwriteId.toString(),
type: params.overwrite.type.toString(),
channel_id: channel.id.toString(),
})
.withChanges(changes);
try {
await builder.commit();
} catch (error) {
Logger.error(
{
error,
guildId: channel.guildId.toString(),
userId: params.userId.toString(),
action,
targetId: params.overwriteId.toString(),
},
'Failed to record guild audit log',
);
}
}
await this.guildAuditLogService.recordPermissionOverwriteDiff({
guildId: channel.guildId,
userId: params.userId,
channelId: channel.id,
previous: existing ? new Map([[targetId, existing]]) : null,
next: new Map([[targetId, nextOverwrite]]),
reason: params.auditLogReason,
});
}
async deleteChannelPermissionOverwrite(params: {
@@ -721,6 +687,7 @@ export class ChannelOperationsService {
channelId: ChannelID;
overwriteId: bigint;
requestCache: RequestCache;
auditLogReason: string | null;
}): Promise<void> {
const channel = await this.channelRepository.channelData.findUnique(params.channelId);
if (!channel || !channel.guildId) throw new UnknownChannelError();
@@ -763,37 +730,15 @@ export class ChannelOperationsService {
});
}
if (removed) {
const previousSnapshot = {
id: params.overwriteId.toString(),
type: removed.type.toString(),
allow: removed.allow.toString(),
deny: removed.deny.toString(),
};
const changes = this.guildAuditLogService.computeChanges(previousSnapshot, null);
const builder = this.guildAuditLogService
.createBuilder(channel.guildId, params.userId)
.withAction(AuditLogActionType.CHANNEL_OVERWRITE_DELETE, params.overwriteId.toString())
.withReason(null)
.withMetadata({
id: params.overwriteId.toString(),
type: removed.type.toString(),
channel_id: channel.id.toString(),
})
.withChanges(changes);
try {
await builder.commit();
} catch (error) {
Logger.error(
{
error,
guildId: channel.guildId.toString(),
userId: params.userId.toString(),
action: AuditLogActionType.CHANNEL_OVERWRITE_DELETE,
targetId: params.overwriteId.toString(),
},
'Failed to record guild audit log',
);
}
const removedTargetId = removed.type === 0 ? createRoleID(params.overwriteId) : createUserID(params.overwriteId);
await this.guildAuditLogService.recordPermissionOverwriteDiff({
guildId: channel.guildId,
userId: params.userId,
channelId: channel.id,
previous: new Map([[removedTargetId, removed]]),
next: null,
reason: params.auditLogReason,
});
}
}
}