internal ChannelData(RestDiscordClient client, AuditLogEntryModel model, bool isCreated) { var changes = new ChannelChanges(client, model); if (isCreated) { Name = changes.Name.NewValue; Topic = changes.Topic.NewValue; Bitrate = changes.Bitrate.NewValue; Overwrites = changes.Overwrites.NewValue; IsNsfw = changes.IsNsfw.NewValue; Slowmode = changes.Slowmode.NewValue; Type = changes.Type.NewValue; } else { Name = changes.Name.OldValue; Topic = changes.Topic.OldValue; Bitrate = changes.Bitrate.OldValue; Overwrites = changes.Overwrites.OldValue; IsNsfw = changes.IsNsfw.OldValue; Slowmode = changes.Slowmode.OldValue; Type = changes.Type.OldValue; } }
internal RoleChanges(RestDiscordClient client, AuditLogEntryModel model) { for (var i = 0; i < model.Changes.Length; i++) { var change = model.Changes[i]; switch (change.Key) { case "name": { Name = AuditLogChange <string> .SingleConvert(change, client.Serializer); break; } case "permissions": { Permissions = AuditLogChange <GuildPermissions> .DoubleConvert <ulong>(change, client.Serializer, x => x); break; } case "color": { Color = AuditLogChange <Color?> .DoubleConvert <int>(change, client.Serializer, x => x == 0 ?(int?)null : x); break; } case "hoist": { IsHoisted = AuditLogChange <bool> .SingleConvert(change, client.Serializer); break; } case "mentionable": { IsMentionable = AuditLogChange <bool> .SingleConvert(change, client.Serializer); break; } default: { client.Log(LogMessageSeverity.Error, $"Unknown change key for {nameof(RoleChanges)}: '{change.Key}'."); break; } } } }
async Task IEventSender.SendAsync(EventBase eventObject) { if (SecurityContext.IsAuthenticated) { eventObject.UserIdentifier = SecurityContext.UserIdentifier; } eventObject.Generated = DateTime.UtcNow; eventObject.UserAgent = HttpContextAccessor.HttpContext.Request.Headers["User-Agent"].FirstOrDefault(); if (eventObject.Audited) { if (DocumentsAPIConfiguration.AuditingEnabled) { var logEntry = new AuditLogEntryModel { Identifier = new AuditLogEntryIdentifier() { OrganizationKey = eventObject.UserIdentifier?.OrganizationKey }, ActionType = eventObject.Name, Details = JsonConvert.SerializeObject(eventObject), Description = eventObject.ToDescription(), Generated = DateTime.UtcNow, OrganizationIdentifier = (eventObject as OrganizationEventBase)?.OrganizationIdentifier, FolderIdentifier = (eventObject as FolderEventBase)?.FolderIdentifier, FileIdentifier = (eventObject as FileEventBase)?.FileIdentifier, UserIdentifier = (eventObject as UserEventBase)?.UserIdentifierTopic, InitiatorUserIdentifier = eventObject.UserIdentifier, UserAgent = eventObject.UserAgent }; var excluded = false; if (DocumentsAPIConfiguration.AuditingExclusion != null && (DocumentsAPIConfiguration.AuditingExclusion == logEntry.UserIdentifier?.UserKey || DocumentsAPIConfiguration.AuditingExclusion == logEntry.InitiatorUserIdentifier?.UserKey)) { excluded = true; } if (!excluded) { await AuditLogEntryStore.InsertAsync(logEntry); } } } Events.Add(eventObject); }
internal EmojiData(RestDiscordClient client, AuditLogEntryModel model, bool isCreated) { var changes = new EmojiChanges(client, model); if (isCreated) { Name = changes.Name.NewValue; } else { Name = changes.Name.OldValue; } }
internal RestAuditLog(RestDiscordClient client, AuditLogModel log, AuditLogEntryModel entry) : base(client, entry.Id) { ResponsibleUserId = entry.UserId; ResponsibleUser = new RestDownloadable <RestUser>(options => client.GetUserAsync(ResponsibleUserId, options)); var userModel = Array.Find(log.Users, x => x.Id == entry.UserId); if (userModel != null) { ResponsibleUser.SetValue(new RestUser(client, userModel)); } Reason = entry.Reason; }
internal RestAuditLog(RestDiscordClient client, AuditLogModel log, AuditLogEntryModel entry) : base(client, entry.Id) { TargetId = entry.TargetId; ResponsibleUserId = entry.UserId; ResponsibleUser = RestFetchable.Create(this, (@this, options) => @this.Client.GetUserAsync(@this.ResponsibleUserId, options)); var userModel = Array.Find(log.Users, x => x.Id == entry.UserId); if (userModel != null) { ResponsibleUser.Value = new RestUser(client, userModel); } Reason = entry.Reason; }
internal WebhookChanges(RestDiscordClient client, AuditLogEntryModel model) { for (var i = 0; i < model.Changes.Length; i++) { var change = model.Changes[i]; switch (change.Key) { case "name": { Name = AuditLogChange <string> .SingleConvert(change, client.Serializer); break; } case "type": { Type = AuditLogChange <WebhookType> .SingleConvert(change, client.Serializer); break; } case "avatar_hash": { AvatarHash = AuditLogChange <string> .SingleConvert(change, client.Serializer); break; } case "channel_id": { ChannelId = AuditLogChange <Snowflake> .DoubleConvert <ulong>(change, client.Serializer, x => x); break; } default: { client.Log(LogMessageSeverity.Error, $"Unknown change key for {nameof(WebhookChanges)}: '{change.Key}'."); break; } } } }
internal OverwriteChanges(RestDiscordClient client, AuditLogEntryModel model) { for (var i = 0; i < model.Changes.Length; i++) { var change = model.Changes[i]; switch (change.Key) { case "id": { TargetId = AuditLogChange <Snowflake> .Convert(change); break; } case "allow": { Allowed = AuditLogChange <ChannelPermissions> .Convert <ulong>(change, x => x); break; } case "deny": { Denied = AuditLogChange <ChannelPermissions> .Convert <ulong>(change, x => x); break; } case "type": { TargetType = AuditLogChange <OverwriteTargetType> .Convert(change); break; } default: { client.Log(LogSeverity.Error, $"Unknown change key for {nameof(OverwriteChanges)}: '{change.Key}'."); break; } } } }
internal WebhookData(RestDiscordClient client, AuditLogEntryModel model, bool isCreated) { var changes = new WebhookChanges(client, model); if (isCreated) { Name = changes.Name.NewValue; Type = changes.Type.NewValue; AvatarHash = changes.AvatarHash.NewValue; ChannelId = changes.ChannelId.NewValue; } else { Name = changes.Name.OldValue; Type = changes.Type.OldValue; AvatarHash = changes.AvatarHash.OldValue; ChannelId = changes.ChannelId.OldValue; } }
internal OverwriteData(RestDiscordClient client, AuditLogEntryModel model, bool isCreated) { var changes = new OverwriteChanges(client, model); if (isCreated) { TargetId = changes.TargetId.NewValue; TargetType = changes.TargetType.NewValue; Allowed = changes.Allowed.NewValue; Denied = changes.Denied.NewValue; } else { TargetId = changes.TargetId.OldValue; TargetType = changes.TargetType.OldValue; Allowed = changes.Allowed.OldValue; Denied = changes.Denied.OldValue; } }
internal RoleData(RestDiscordClient client, AuditLogEntryModel model, bool isCreated) { var changes = new RoleChanges(client, model); if (isCreated) { Name = changes.Name.NewValue; Permissions = changes.Permissions.NewValue; Color = changes.Color.NewValue; IsHoisted = changes.IsHoisted.NewValue; IsMentionable = changes.IsMentionable.NewValue; } else { Name = changes.Name.OldValue; Permissions = changes.Permissions.OldValue; Color = changes.Color.OldValue; IsHoisted = changes.IsHoisted.OldValue; IsMentionable = changes.IsMentionable.OldValue; } }
internal EmojiChanges(RestDiscordClient client, AuditLogEntryModel model) { for (var i = 0; i < model.Changes.Length; i++) { var change = model.Changes[i]; switch (change.Key) { case "name": { Name = AuditLogChange <string> .Convert(change); break; } default: { client.Log(LogSeverity.Error, $"Unknown change key for {nameof(WebhookChanges)}: '{change.Key}'."); break; } } } }
internal MemberChanges(RestDiscordClient client, AuditLogEntryModel model) { for (var i = 0; i < model.Changes.Length; i++) { var change = model.Changes[i]; switch (change.Key) { case "nick": { Nick = AuditLogChange <string> .Convert(change); break; } case "deaf": { IsDeafened = AuditLogChange <bool> .Convert(change); break; } case "mute": { IsMuted = AuditLogChange <bool> .Convert(change); break; } default: { client.Log(LogSeverity.Error, $"Unknown change key for {nameof(MemberChanges)}: '{change.Key}'."); break; } } } }
public static AuditLogEntry ToEntity(this AuditLogEntryModel model) { return(new AuditLogEntry { AuditLogEntryID = model.Identifier?.AuditLogID ?? 0, ActionType = model.ActionType, Description = model.Description, InitiatorOrganizationKey = model.InitiatorUserIdentifier?.OrganizationKey, InitiatorUserKey = model.InitiatorUserIdentifier?.UserKey, UserAgent = model.UserAgent, OrganizationKey = model.OrganizationIdentifier?.OrganizationKey ?? model.FolderIdentifier?.OrganizationKey ?? model.FileIdentifier?.OrganizationKey ?? model.UserIdentifier?.OrganizationKey, FolderKey = model.FolderIdentifier?.FolderKey ?? model.FileIdentifier?.FolderKey, FileKey = model.FileIdentifier?.FileKey, UserKey = model.UserIdentifier?.UserKey, Details = model.Details, Generated = model.Generated }); }
internal RestMemberKickedAuditLog(RestDiscordClient client, AuditLogModel log, AuditLogEntryModel entry) : base(client, log, entry) { }
internal RestMessageUnpinnedAuditLog(RestDiscordClient client, AuditLogModel log, AuditLogEntryModel entry) : base(client, log, entry) { ChannelId = entry.Options.ChannelId; MessageId = entry.Options.MessageId; }
internal static RestAuditLog Create(RestDiscordClient client, AuditLogModel log, AuditLogEntryModel entry) => entry.ActionType switch {
public static AuditLogEntryModel ToModel(this AuditLogEntry entity) { if (entity != null) { var model = new AuditLogEntryModel { Identifier = new AuditLogEntryIdentifier { OrganizationKey = entity.OrganizationKey, AuditLogID = entity.AuditLogEntryID }, ActionType = entity.ActionType, Generated = entity.Generated, UserAgent = entity.UserAgent, InitiatorUserIdentifier = new UserIdentifier { OrganizationKey = entity.InitiatorOrganizationKey, UserKey = entity.InitiatorUserKey }, Details = entity.Details, Description = entity.Description, }; var fileIdentifier = new FileIdentifier { OrganizationKey = entity.OrganizationKey, FolderKey = entity.FolderKey, FileKey = entity.FileKey }; model.FileIdentifier = fileIdentifier.IsValid ? fileIdentifier : null; var folderIdentifier = new FolderIdentifier { OrganizationKey = entity.OrganizationKey, FolderKey = entity.FolderKey, }; model.FolderIdentifier = folderIdentifier.IsValid ? folderIdentifier : null; var organizationIdentifier = new OrganizationIdentifier { OrganizationKey = entity.OrganizationKey, }; model.OrganizationIdentifier = organizationIdentifier.IsValid ? organizationIdentifier : null; var userIdentifier = new UserIdentifier { OrganizationKey = entity.OrganizationKey, UserKey = entity.UserKey, }; model.UserIdentifier = userIdentifier.IsValid ? userIdentifier : null; return(model); } else { return(null); } }
internal RestChannelCreatedAuditLog(RestDiscordClient client, AuditLogModel auditLogModel, AuditLogEntryModel model) : base(client, auditLogModel, model) { Metadata = new RestAuditLogChannelMetadata(client, auditLogModel, model); }
internal ChannelChanges(RestDiscordClient client, AuditLogEntryModel model) { for (var i = 0; i < model.Changes.Length; i++) { var change = model.Changes[i]; switch (change.Key) { case "name": { Name = AuditLogChange <string> .Convert(change); break; } case "topic": { Topic = AuditLogChange <string> .Convert(change); break; } case "bitrate": { Bitrate = AuditLogChange <int> .Convert(change); break; } case "permission_overwrites": { var overwritesBefore = Optional <IReadOnlyList <RestOverwrite> > .Empty; if (change.OldValue.HasValue) { var models = change.OldValue.Value.ToType <OverwriteModel[]>(); overwritesBefore = new Optional <IReadOnlyList <RestOverwrite> >( models.ToReadOnlyList((client, model), (x, tuple) => { var(client, model) = tuple; return(new RestOverwrite(client, model.TargetId.Value, x)); })); } var overwritesAfter = Optional <IReadOnlyList <RestOverwrite> > .Empty; if (change.NewValue.HasValue) { var models = change.NewValue.Value.ToType <OverwriteModel[]>(); overwritesAfter = new Optional <IReadOnlyList <RestOverwrite> >( models.ToReadOnlyList((client, model), (x, tuple) => { var(client, model) = tuple; return(new RestOverwrite(client, model.TargetId.Value, x)); })); } Overwrites = new AuditLogChange <IReadOnlyList <RestOverwrite> >(overwritesBefore, overwritesAfter); break; } case "nsfw": { IsNsfw = AuditLogChange <bool> .Convert(change); break; } case "rate_limit_per_user": { Slowmode = AuditLogChange <int> .Convert(change); break; } case "type": { Type = AuditLogChange <AuditLogChannelType> .Convert(change); break; } default: { client.Log(LogSeverity.Error, $"Unknown change key for {nameof(ChannelChanges)}: '{change.Key}'."); break; } } } }
internal RestGuildUpdatedAuditLog(RestDiscordClient client, AuditLogModel auditLogModel, AuditLogEntryModel model) : base(client, auditLogModel, model) { Metadata = new RestAuditLogGuildMetadata(client, auditLogModel, model); }
internal RestChannelDeletedAuditLog(RestDiscordClient client, AuditLogModel log, AuditLogEntryModel entry) : base(client, log, entry) { Data = new ChannelData(client, entry, false); }
internal RestUnknownAuditLog(RestDiscordClient client, AuditLogModel model, AuditLogEntryModel entryModel) : base(client, model, entryModel) { Type = (int)entryModel.ActionType; }
internal RestAuditLogGuildMetadata(RestDiscordClient client, AuditLogModel auditLogModel, AuditLogEntryModel model) : base(client) { for (var i = 0; i < model.Changes.Length; i++) { var change = model.Changes[i]; switch (change.Key) { case "name": { Name = new AuditLogValue <string>(change); break; } case "icon_hash": { IconHash = new AuditLogValue <string>(change); break; } case "splash_hash": { SplashHash = new AuditLogValue <string>(change); break; } case "owner_id": { OwnerId = new AuditLogValue <ulong>(change); var ownerBeforeModel = Array.Find(auditLogModel.Users, x => x.Id == OwnerId.OldValue); var ownerAfterModel = Array.Find(auditLogModel.Users, x => x.Id == OwnerId.NewValue); Owner = new AuditLogValue <RestUser>( ownerBeforeModel != null ? new RestUser(client, ownerBeforeModel) : Optional <RestUser> .Empty, ownerAfterModel != null ? new RestUser(client, ownerAfterModel) : Optional <RestUser> .Empty); break; } case "region": { VoiceRegionId = new AuditLogValue <string>(change); break; } case "afk_channel_id": { AfkChannelId = new AuditLogValue <ulong?>(change); break; } case "afk_timeout": { AfkTimeout = new AuditLogValue <int>(change); break; } case "mfa_level": { MfaLevel = new AuditLogValue <MfaLevel>(change); break; } case "verification_level": { VerificationLevel = new AuditLogValue <VerificationLevel>(change); break; } case "explicit_content_filter": { ContentFilterLevel = new AuditLogValue <ContentFilterLevel>(change); break; } case "default_message_notifications": { DefaultNotificationLevel = new AuditLogValue <DefaultNotificationLevel>(change); break; } case "vanity_url_code": { VanityUrlCode = new AuditLogValue <string>(change); break; } case "widget_enabled": { IsWidgetEnabled = new AuditLogValue <bool>(change); break; } case "widget_channel_id": { WidgetChannelId = new AuditLogValue <ulong?>(change); break; } case "system_channel_id": { SystemChannelId = new AuditLogValue <ulong?>(change); break; } } } }
internal RestEmojiCreatedAuditLog(RestDiscordClient client, AuditLogModel log, AuditLogEntryModel entry) : base(client, log, entry) { Data = new EmojiData(client, entry, true); }
internal RestOverwriteUpdatedAuditLog(RestDiscordClient client, AuditLogModel log, AuditLogEntryModel entry) : base(client, log, entry) { Changes = new OverwriteChanges(client, entry); }
//public RoleData Data { get; } internal RestInviteCreatedAuditLog(RestDiscordClient client, AuditLogModel log, AuditLogEntryModel entry) : base(client, log, entry) { //Data = new RoleData(client, entry, true); }
/// <inheritdoc/> public Task WriteAsync(AuditLogEntryModel entry) => _eventHub.SendAsync(JToken.FromObject(entry), "application/x-audit-log-v1-json", entry.OperationId);
internal RestMemberRolesUpdatedAuditLog(RestDiscordClient client, AuditLogModel log, AuditLogEntryModel entry) : base(client, log, entry) { for (var i = 0; i < entry.Changes.Length; i++) { var change = entry.Changes[i]; switch (change.Key) { case "$add": { RolesAdded = AuditLogChange <IReadOnlyList <Role> > .Convert <RoleModel[]>(change, x => x.ToReadOnlyList(y => new Role(y))).NewValue; break; } case "$remove": { RolesRemoved = AuditLogChange <IReadOnlyList <Role> > .Convert <RoleModel[]>(change, x => x.ToReadOnlyList(y => new Role(y))).NewValue; break; } default: { client.Log(LogSeverity.Error, $"Unknown change key for {nameof(RestMemberRolesUpdatedAuditLog)}: '{change.Key}'."); break; } } } }
/// <inheritdoc/> public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // Create new audit log id context.HttpContext.TraceIdentifier = Guid.NewGuid().ToString(); // Get session id if present string sessionId = null; if (context.HttpContext.Request.Headers.TryGetValue( HttpHeader.TrackingId, out var id)) { sessionId = id; } // Create entry var entry = new AuditLogEntryModel { Id = context.HttpContext.TraceIdentifier, User = context.HttpContext.User?.Identity?.Name, SessionId = sessionId, OperationId = context.ActionDescriptor.Id, OperationName = $"{context.HttpContext.Request.Method} {context.HttpContext.Request.Path}", TimeStamp = DateTime.UtcNow, Parameters = context.ActionArguments }; // Invoke action context.HttpContext.Items.Add(HttpContextEx.kEntryKey, entry); var result = await next.Invoke(); // Convert result if (result.Canceled) { entry.Result = null; entry.Type = AuditLogEntryType.Cancellation; } else if (result.Exception != null) { entry.Result = result.Exception; entry.Type = AuditLogEntryType.Exception; } else { switch (result.Result) { case ObjectResult obj: entry.Result = obj.Value; break; case JsonResult json: entry.Result = json.Value; break; case EmptyResult empty: entry.Result = null; break; default: _logger.Error("Unknown result type {type}", result.Result.GetType()); entry.Result = result.Result; break; } } entry.Completed = DateTime.UtcNow; try { await _writer.WriteAsync(entry); } catch (Exception ex) { _logger.Error(ex, "Failed to write audit log for activity {id}", id); } // Let user know of the activity / audit id and return session id context.HttpContext.Response.Headers.Add(HttpHeader.ActivityId, id); if (sessionId != null) { context.HttpContext.Response.Headers.Add(HttpHeader.TrackingId, sessionId); } }