Skip to content

Commit

Permalink
Add deleting of audit logging; fix user roles pagination; Add dynamic…
Browse files Browse the repository at this point in the history
… pager;
  • Loading branch information
skoruba committed Nov 4, 2019
1 parent 4637a38 commit 2326155
Show file tree
Hide file tree
Showing 22 changed files with 620 additions and 247 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;

namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Log
{
public class AuditLogFilterDto
{
public string Event { get; set; }

public string Source { get; set; }

public string Category { get; set; }

public DateTime? Created { get; set; }

public string SubjectIdentifier { get; set; }

public string SubjectName { get; set; }

public int PageSize { get; set; } = 10;

public int Page { get; set; } = 1;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Log
{
Expand All @@ -9,6 +11,8 @@ public AuditLogsDto()
Logs = new List<AuditLogDto>();
}

[Required]
public DateTime? DeleteOlderThan { get; set; }

public List<AuditLogDto> Logs { get; set; }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using Skoruba.AuditLogging.EntityFramework.Entities;
using Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Log;
using Skoruba.IdentityServer4.Admin.BusinessLogic.Mappers;
Expand All @@ -7,23 +8,27 @@

namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Services
{
public class AuditLogService<TAuditLog> : IAuditLogService
public class AuditLogService<TAuditLog> : IAuditLogService
where TAuditLog : AuditLog
{
private readonly IAuditLogRepository<TAuditLog> _auditLogRepository;
protected readonly IAuditLogRepository<TAuditLog> AuditLogRepository;

public AuditLogService(IAuditLogRepository<TAuditLog> auditLogRepository)
{
_auditLogRepository = auditLogRepository;
AuditLogRepository = auditLogRepository;
}

public async Task<AuditLogsDto> GetAsync(int page = 1, int pageSize = 10)
{
var pagedList = await _auditLogRepository.GetAsync(page, pageSize);

public async Task<AuditLogsDto> GetAsync(AuditLogFilterDto filters)
{
var pagedList = await AuditLogRepository.GetAsync(filters.Event, filters.Source, filters.Category, filters.Created, filters.SubjectIdentifier, filters.SubjectName, filters.Page, filters.PageSize);
var auditLogsDto = pagedList.ToModel();

return auditLogsDto;
}

public virtual async Task DeleteLogsOlderThanAsync(DateTime deleteOlderThan)
{
await AuditLogRepository.DeleteLogsOlderThanAsync(deleteOlderThan);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Log;

namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Services.Interfaces
{
public interface IAuditLogService
{
Task<AuditLogsDto> GetAsync(int page = 1, int pageSize = 10);
Task<AuditLogsDto> GetAsync(AuditLogFilterDto filters);

Task DeleteLogsOlderThanAsync(DateTime deleteOlderThan);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Threading.Tasks;
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Skoruba.AuditLogging.EntityFramework.DbContexts;
using Skoruba.AuditLogging.EntityFramework.Entities;
Expand All @@ -19,20 +21,42 @@ public AuditLogRepository(TDbContext dbContext)
DbContext = dbContext;
}

public async Task<PagedList<TAuditLog>> GetAsync(int page = 1, int pageSize = 10)
public async Task<PagedList<TAuditLog>> GetAsync(string @event, string source, string category, DateTime? created, string subjectIdentifier, string subjectName, int page = 1, int pageSize = 10)
{
var pagedList = new PagedList<TAuditLog>();

var auditLogs = await DbContext.AuditLog
.PageBy(x => x.Id, page, pageSize)
.WhereIf(!string.IsNullOrEmpty(subjectIdentifier), log => log.SubjectIdentifier.Contains(subjectIdentifier))
.WhereIf(!string.IsNullOrEmpty(subjectName), log => log.SubjectName.Contains(subjectName))
.WhereIf(!string.IsNullOrEmpty(@event), log => log.Event.Contains(@event))
.WhereIf(!string.IsNullOrEmpty(source), log => log.Source.Contains(source))
.WhereIf(!string.IsNullOrEmpty(category), log => log.Category.Contains(category))
.WhereIf(created.HasValue, log => log.Created.Date == created.Value.Date)
.ToListAsync();

pagedList.Data.AddRange(auditLogs);
pagedList.PageSize = pageSize;
pagedList.TotalCount = await DbContext.AuditLog.CountAsync();
pagedList.TotalCount = await DbContext.AuditLog
.WhereIf(!string.IsNullOrEmpty(subjectIdentifier), log => log.SubjectIdentifier.Contains(subjectIdentifier))
.WhereIf(!string.IsNullOrEmpty(subjectName), log => log.SubjectName.Contains(subjectName))
.WhereIf(!string.IsNullOrEmpty(@event), log => log.Event.Contains(@event))
.WhereIf(!string.IsNullOrEmpty(source), log => log.Source.Contains(source))
.WhereIf(!string.IsNullOrEmpty(category), log => log.Category.Contains(category))
.WhereIf(created.HasValue, log => log.Created.Date == created.Value.Date)
.CountAsync();

return pagedList;
}

public virtual async Task DeleteLogsOlderThanAsync(DateTime deleteOlderThan)
{
var logsToDelete = await DbContext.AuditLog.Where(x => x.Created.Date < deleteOlderThan.Date).ToListAsync();

return pagedList;
if (logsToDelete.Count == 0) return;

DbContext.AuditLog.RemoveRange(logsToDelete);
await DbContext.SaveChangesAsync();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using Skoruba.AuditLogging.EntityFramework.Entities;
using Skoruba.IdentityServer4.Admin.EntityFramework.Extensions.Common;

namespace Skoruba.IdentityServer4.Admin.EntityFramework.Repositories.Interfaces
{
public interface IAuditLogRepository<TAuditLog> where TAuditLog : AuditLog
{
Task<PagedList<TAuditLog>> GetAsync(int page = 1, int pageSize = 10);
Task<PagedList<TAuditLog>> GetAsync(string @event, string source, string category, DateTime? created, string subjectIdentifier, string subjectName, int page = 1, int pageSize = 10);

Task DeleteLogsOlderThanAsync(DateTime deleteOlderThan);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,12 @@ public async Task<IActionResult> Users(int? page, string search)
}

[HttpGet]
public async Task<IActionResult> RoleUsers(string roleId, int? page, string search)
public async Task<IActionResult> RoleUsers(string id, int? page, string search)
{
ViewBag.Search = search;
var roleUsers = await _identityService.GetRoleUsersAsync(roleId, search, page ?? 1);
var roleUsers = await _identityService.GetRoleUsersAsync(id, search, page ?? 1);

var roleDto = await _identityService.GetRoleAsync(roleId);
var roleDto = await _identityService.GetRoleAsync(id);
ViewData["RoleName"] = roleDto.Name;

return View(roleUsers);
Expand Down
25 changes: 22 additions & 3 deletions src/Skoruba.IdentityServer4.Admin/Controllers/LogController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ public async Task<IActionResult> ErrorsLog(int? page, string search)
}

[HttpGet]
public async Task<IActionResult> AuditLog(int? page, string search)
public async Task<IActionResult> AuditLog([FromQuery]AuditLogFilterDto filters)
{
ViewBag.Search = search;
var logs = await _auditLogService.GetAsync(page ?? 1);
ViewBag.SubjectIdentifier = filters.SubjectIdentifier;
ViewBag.SubjectName = filters.SubjectName;
ViewBag.Event = filters.Event;
ViewBag.Source = filters.Source;
ViewBag.Category = filters.Category;

var logs = await _auditLogService.GetAsync(filters);

return View(logs);
}
Expand All @@ -53,5 +58,19 @@ public async Task<IActionResult> DeleteLogs(LogsDto logs)

return RedirectToAction(nameof(ErrorsLog));
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteAuditLogs(AuditLogsDto logs)
{
if (!ModelState.IsValid)
{
return View(nameof(AuditLog), logs);
}

await _auditLogService.DeleteLogsOlderThanAsync(logs.DeleteOlderThan.Value);

return RedirectToAction(nameof(AuditLog));
}
}
}
36 changes: 33 additions & 3 deletions src/Skoruba.IdentityServer4.Admin/Helpers/PagerHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;

namespace Skoruba.IdentityServer4.Admin.Helpers
{
public static class PagerHelpers
{
public static int GetTotalPages(int pageSize, int totalCount)
{
return (int)Math.Ceiling((double)totalCount / pageSize);
return (int) Math.Ceiling((double) totalCount / pageSize);
}

public static bool IsActivePage(int currentPage, int currentIteration)
Expand Down Expand Up @@ -34,7 +39,7 @@ public static int GetMinPageToRender(int maxPages, int totalPages, int currentPa
var currentMaxPages = GetMaxPageToRender(maxPages, totalPages, currentPage);

if (currentMaxPages == defaultPageNumber) return currentMaxPages;

if (currentMaxPages == totalPages)
{
currentMaxPages = GetMaxPage(maxPages, totalPages, currentPage);
Expand All @@ -47,7 +52,7 @@ public static int GetMinPageToRender(int maxPages, int totalPages, int currentPa

public static int GetMaxPage(int maxPages, int totalPages, int currentPage)
{
var result = (int)Math.Ceiling((double)currentPage / maxPages);
var result = (int) Math.Ceiling((double) currentPage / maxPages);
return result * maxPages;
}

Expand All @@ -73,5 +78,30 @@ public static int GetCurrentPage(string currentPage)
return 1;
}
}

public static QueryString GetQueryString(HttpContext context, int page)
{
const string pageKey = "page";

var queryString = context.Request.QueryString.Value;
var queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(queryString);
var items = queryDictionary.SelectMany(x => x.Value, (col, value) => new KeyValuePair<string, string>(col.Key, value)).ToList();

// Remove existing page key
items.RemoveAll(x => x.Key == pageKey);

// Setup new page key
var queryBuilder = new QueryBuilder(items)
{
{ pageKey, page.ToString() }
};

return queryBuilder.ToQueryString();
}

public static string GetUrl(string baseUrl, QueryString queryString)
{
return $"{baseUrl}{queryString}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,33 @@
<data name="Action" xml:space="preserve">
<value>Action</value>
</data>
<data name="Are you sure?" xml:space="preserve">
<value>Are you sure?</value>
</data>
<data name="Audit Log" xml:space="preserve">
<value>Audit Log</value>
</data>
<data name="Category" xml:space="preserve">
<value>Category</value>
</data>
<data name="Created" xml:space="preserve">
<value>Created</value>
</data>
<data name="Delete logs older than" xml:space="preserve">
<value>Delete logs older than</value>
</data>
<data name="Detail" xml:space="preserve">
<value>Detail</value>
</data>
<data name="Event" xml:space="preserve">
<value>Event</value>
</data>
<data name="No - close" xml:space="preserve">
<value>No - close</value>
</data>
<data name="Search" xml:space="preserve">
<value>Search</value>
</data>
<data name="Show detail" xml:space="preserve">
<value>Show detail</value>
</data>
Expand All @@ -138,4 +156,16 @@
<data name="Subject" xml:space="preserve">
<value>Subject</value>
</data>
<data name="Subject Identifier" xml:space="preserve">
<value>Subject Identifier</value>
</data>
<data name="Subject Name" xml:space="preserve">
<value>Subject Name</value>
</data>
<data name="Warning" xml:space="preserve">
<value>Warning</value>
</data>
<data name="Yes - delete" xml:space="preserve">
<value>Yes - delete</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -117,46 +117,10 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ButtonClone" xml:space="preserve">
<value>Clone Client</value>
<data name="FirstButtonText" xml:space="preserve">
<value>First</value>
</data>
<data name="InfoDescription" xml:space="preserve">
<value>The client secrets will not be cloned.</value>
</data>
<data name="InfoTitle" xml:space="preserve">
<value>Info:</value>
</data>
<data name="LabelCloneClientClaims" xml:space="preserve">
<value>Client Claims</value>
</data>
<data name="LabelCloneClientCorsOrigins" xml:space="preserve">
<value>Client Cors Origins</value>
</data>
<data name="LabelCloneClientGrantTypes" xml:space="preserve">
<value>Client Grant Types</value>
</data>
<data name="LabelCloneClientIdPRestrictions" xml:space="preserve">
<value>Client IdP Restrictions</value>
</data>
<data name="LabelCloneClientPostLogoutRedirectUris" xml:space="preserve">
<value>Client Post Logout Redirect Uris</value>
</data>
<data name="LabelCloneClientProperties" xml:space="preserve">
<value>Client Properties</value>
</data>
<data name="LabelCloneClientRedirectUris" xml:space="preserve">
<value>Client Redirect Uris</value>
</data>
<data name="LabelCloneClientScopes" xml:space="preserve">
<value>Client Scopes</value>
</data>
<data name="NavigationClients" xml:space="preserve">
<value>Clients</value>
</data>
<data name="PageTitle" xml:space="preserve">
<value>Clone Client</value>
</data>
<data name="PanelTitle" xml:space="preserve">
<value>Client</value>
<data name="LastButtonText" xml:space="preserve">
<value>Last</value>
</data>
</root>
Loading

0 comments on commit 2326155

Please sign in to comment.