Skip to content

Commit

Permalink
Merge pull request #3 from maximgorbatyuk/dev
Browse files Browse the repository at this point in the history
timeout
  • Loading branch information
maximgorbatyuk authored Aug 28, 2022
2 parents bc3cfb2 + 29265c6 commit b89ee32
Show file tree
Hide file tree
Showing 13 changed files with 92 additions and 24 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Build and test

on:
push:
branches: [main]
branches: [dev]
pull_request:
branches: [main]
branches: [main,dev]

jobs:
Test:
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# MaximGorbatyuk.DatabaseSqlEndpoints

![GitHub Workflow Status](https://img.shields.io/github/workflow/status/maximgorbatyuk/MaximGorbatyuk.DatabaseSqlEndpoints/Build%20and%20test) ![Nuget](https://img.shields.io/nuget/dt/MaximGorbatyuk.DatabaseSqlEndpoints) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/maximgorbatyuk/MaximGorbatyuk.DatabaseSqlEndpoints) ![GitHub](https://img.shields.io/github/license/maximgorbatyuk/MaximGorbatyuk.DatabaseSqlEndpoints)

This nuget allows you to view table content of your ASP.NET core application during runtime. The nuget creates a special endpoint and then return tables and data represented in html form.

## Get started
Expand All @@ -21,7 +23,7 @@ class Startup
// ... some settings
app
.UseDatabaseTable<AwesomeDbContext>()
.UseSqlEndpoints<AwesomeDbContext>()
.UseTableOutputEndpoint() // default route is /database-sql-endpoints/table
.UseReadEndpoint() // default route is /database-sql-endpoints/read
.UseExecuteEndpoint(); // default route is /database-sql-endpoints/execute
Expand All @@ -47,11 +49,11 @@ Open `https:localhost:5001/database-sql-endpoints/table?tableName=<tableName>` i

Send the following POST request:

```plaintext
```bash

POST https:localhost:5001/database-sql-endpoints/read

BODY Json:
BODY:
{
"query": "select 1;"
}
Expand All @@ -62,11 +64,11 @@ BODY Json:

Send the following POST request:

```plaintext
```bash

POST https:localhost:5001/database-sql-endpoints/execute

BODY Json:
BODY:
{
"query": "delete fronm users;"
}
Expand Down
5 changes: 5 additions & 0 deletions docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Resources

- https://lukelowrey.com/use-github-actions-to-publish-nuget-packages/
- https://acraven.medium.com/a-nuget-package-workflow-using-github-actions-7da8c6557863
- https://stackoverflow.com/questions/58139175/running-actions-in-another-directory
7 changes: 7 additions & 0 deletions src/MaximGorbatyuk.DatabaseSqlEndpoints/Constants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace MaximGorbatyuk.DatabaseSqlEndpoints
{
public static class Constants
{
internal const int DefaultSqlCommandTimeoutSec = 30;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,22 @@ internal class DatabaseTablesSettings<TContext> : IDatabaseTablesSettings<TConte

public SqlEngine SqlEngine { get; }

public DatabaseTablesSettings(IApplicationBuilder app, int? port, bool checkForAuthentication, string roleToCheckForAuthorization, SqlEngine sqlEngine)
public int TimeoutSec { get; }

public DatabaseTablesSettings(
IApplicationBuilder app,
int? port,
bool checkForAuthentication,
string roleToCheckForAuthorization,
SqlEngine sqlEngine,
int timeoutSec = Constants.DefaultSqlCommandTimeoutSec)
{
App = app;
Port = port;
CheckForAuthentication = checkForAuthentication;
RoleToCheckForAuthorization = roleToCheckForAuthorization;
SqlEngine = sqlEngine;
TimeoutSec = timeoutSec;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,22 @@ public static class DatabaseTablesViewExtensions
public const string DefaultReadRoute = "/database-sql-endpoints/read";
public const string DefaultExecuteRoute = "/database-sql-endpoints/execute";

public static IDatabaseTablesSettings<TDbContext> UseDatabaseTable<TDbContext>(
public static IDatabaseTablesSettings<TDbContext> UseSqlEndpoints<TDbContext>(
this IApplicationBuilder app,
int? port = null,
bool checkForAuthentication = false,
string roleToCheckForAuthorization = null,
SqlEngine sqlEngine = default)
SqlEngine sqlEngine = default,
int timeoutSeconds = Constants.DefaultSqlCommandTimeoutSec)
where TDbContext : DbContext
{
return new DatabaseTablesSettings<TDbContext>(app, port, checkForAuthentication, roleToCheckForAuthorization, sqlEngine);
return new DatabaseTablesSettings<TDbContext>(
app,
port,
checkForAuthentication,
roleToCheckForAuthorization,
sqlEngine,
timeoutSeconds);
}

/// <summary>
Expand All @@ -31,7 +38,9 @@ public static IDatabaseTablesSettings<TDbContext> UseDatabaseTable<TDbContext>(
/// <param name="settings">Settings.</param>
/// <param name="path">Path.</param>
/// <returns>Settings instance.</returns>
public static IDatabaseTablesSettings<TDbContext> UseTableOutputEndpoint<TDbContext>(this IDatabaseTablesSettings<TDbContext> settings, PathString path = default)
public static IDatabaseTablesSettings<TDbContext> UseTableOutputEndpoint<TDbContext>(
this IDatabaseTablesSettings<TDbContext> settings,
PathString path = default)
where TDbContext : DbContext
{
return new MiddlewareRoute<DatabaseTablesMiddleware<TDbContext>, TDbContext>(
Expand All @@ -50,7 +59,9 @@ public static IDatabaseTablesSettings<TDbContext> UseTableOutputEndpoint<TDbCont
/// <param name="settings">Settings.</param>
/// <param name="path">Path.</param>
/// <returns>Settings instance.</returns>
public static IDatabaseTablesSettings<TDbContext> UseReadEndpoint<TDbContext>(this IDatabaseTablesSettings<TDbContext> settings, PathString path = default)
public static IDatabaseTablesSettings<TDbContext> UseReadEndpoint<TDbContext>(
this IDatabaseTablesSettings<TDbContext> settings,
PathString path = default)
where TDbContext : DbContext
{
return new MiddlewareRoute<ReadSQlMiddleware<TDbContext>, TDbContext>(
Expand All @@ -67,7 +78,9 @@ public static IDatabaseTablesSettings<TDbContext> UseReadEndpoint<TDbContext>(th
/// <param name="settings">Settings.</param>
/// <param name="path">Path.</param>
/// <returns>Settings instance.</returns>
public static IDatabaseTablesSettings<TDbContext> UseExecuteEndpoint<TDbContext>(this IDatabaseTablesSettings<TDbContext> settings, PathString path = default)
public static IDatabaseTablesSettings<TDbContext> UseExecuteEndpoint<TDbContext>(
this IDatabaseTablesSettings<TDbContext> settings,
PathString path = default)
where TDbContext : DbContext
{
return new MiddlewareRoute<ExecuteSQlMiddleware<TDbContext>, TDbContext>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public interface IDatabaseTablesSettingsBase

SqlEngine SqlEngine { get; }

int TimeoutSec { get; }

bool HasRole => RoleToCheckForAuthorization is not null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package >
<metadata>
<id>MaximGorbatyuk.DatabaseSqlEndpoints</id>
<version>1.0.1</version>
<version>1.0.2</version>
<title>MaximGorbatyuk.DatabaseSqlEndpoints for executing SQL commands</title>
<authors>@maximgorbatyuk</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
Expand Down
6 changes: 5 additions & 1 deletion src/MaximGorbatyuk.DatabaseSqlEndpoints/MiddlewareRoute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ internal class MiddlewareRoute<TMiddleware, TDbContext>
private readonly PathString _path;
private readonly IDatabaseTablesSettings<TDbContext> _settings;

public MiddlewareRoute(IDatabaseTablesSettings<TDbContext> settings, PathString path, string methodName, string defaultPathRoute)
public MiddlewareRoute(
IDatabaseTablesSettings<TDbContext> settings,
PathString path,
string methodName,
string defaultPathRoute)
{
_path = !path.HasValue ? new PathString(defaultPathRoute) : path;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,22 @@ namespace MaximGorbatyuk.DatabaseSqlEndpoints.Middlewares
public class DatabaseTablesMiddleware<TDbContext> : DatabaseTableBaseMiddleware<TDbContext>
where TDbContext : DbContext
{
public DatabaseTablesMiddleware(RequestDelegate next, IOptions<IDatabaseTablesSettingsBase> settingsBase)
public DatabaseTablesMiddleware(
RequestDelegate next,
IOptions<IDatabaseTablesSettingsBase> settingsBase)
: base(next, settingsBase)
{
}

private async Task<string> PageAsync(TDbContext db, string tableName)
private async Task<string> PageAsync(
TDbContext db,
string tableName)
{
var table = await new ReadTableSqlCommand<TDbContext>(query: $"SELECT * FROM {tableName}", db).AsDataTableAsync();
var table = await new ReadTableSqlCommand<TDbContext>(
query: $"SELECT * FROM {tableName}",
db,
Settings.TimeoutSec)
.AsDataTableAsync();

return new DataTableTextOutput(table).AsText();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ public ExecuteSQlMiddleware(RequestDelegate next, IOptions<IDatabaseTablesSettin
{
}

protected override async Task<string> ResponseContentAsync(string query, HttpContext httpContext, TDbContext context)
protected override async Task<string> ResponseContentAsync(
string query,
HttpContext httpContext,
TDbContext context)
{
context.Database.SetCommandTimeout(Settings.TimeoutSec);
var result = await context.Database.ExecuteSqlRawAsync(query);
return $"Rows affected: {result}";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,18 @@ public ReadSQlMiddleware(RequestDelegate next, IOptions<IDatabaseTablesSettingsB
{
}

protected override async Task<string> ResponseContentAsync(string query, HttpContext httpContext, TDbContext context)
protected override async Task<string> ResponseContentAsync(
string query,
HttpContext httpContext,
TDbContext context)
{
return new DataTableTextOutput(
await new ReadTableSqlCommand<TDbContext>(query, context).AsDataTableAsync()).AsText();
await new ReadTableSqlCommand<TDbContext>(
query,
context,
Settings.TimeoutSec)
.AsDataTableAsync())
.AsText();
}
}
}
10 changes: 8 additions & 2 deletions src/MaximGorbatyuk.DatabaseSqlEndpoints/ReadTableSqlCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ public class ReadTableSqlCommand<TContext>
{
private readonly string _query;
private readonly TContext _context;
private readonly int _timeoutSeconds;

public ReadTableSqlCommand(string query, TContext context)
public ReadTableSqlCommand(
string query,
TContext context,
int? timeoutSeconds)
{
if (string.IsNullOrEmpty(query))
{
Expand All @@ -20,6 +24,7 @@ public ReadTableSqlCommand(string query, TContext context)

_query = query;
_context = context;
_timeoutSeconds = timeoutSeconds ?? Constants.DefaultSqlCommandTimeoutSec;
}

public async Task<DataTable> AsDataTableAsync()
Expand All @@ -30,12 +35,13 @@ public async Task<DataTable> AsDataTableAsync()
await using var cmd = _context.Database.GetDbConnection().CreateCommand();

#pragma warning disable CA2100
cmd.CommandTimeout = _timeoutSeconds;
cmd.CommandText = _query;
#pragma warning restore CA2100

if (cmd.Connection is not null)
{
await cmd.Connection?.OpenAsync();
await cmd.Connection.OpenAsync();
table.Load(await cmd.ExecuteReaderAsync());
}

Expand Down

0 comments on commit b89ee32

Please sign in to comment.