Skip to content

Commit

Permalink
v2.8.4 initial
Browse files Browse the repository at this point in the history
  • Loading branch information
vbilopav committed Jun 22, 2024
1 parent bdba427 commit 4eaebb0
Show file tree
Hide file tree
Showing 15 changed files with 152 additions and 28 deletions.
2 changes: 1 addition & 1 deletion NpgsqlRest/Defaults/DefaultEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ internal static class DefaultEndpoint
routineEndpoint.LogCallback = LoggerMessage.Define<string, string>(LogLevel.Information,
new EventId(5, nameof(routineEndpoint.LogCallback)),
"{parameters}{command}",
Logger.LogDefineOptions);
NpgsqlRestLogger.LogDefineOptions);
}
else
{
Expand Down
11 changes: 6 additions & 5 deletions NpgsqlRest/MiddlewareExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,22 @@
NpgsqlRest.RoutineEndpoint endpoint,
NpgsqlRest.IRoutineSourceParameterFormatter formatter
);

using NpgsqlRest.Auth;
using System.Reflection.PortableExecutable;

namespace NpgsqlRest;

public static class NpgsqlRestMiddlewareExtensions
{
private static ILogger? logger = null;
public static ILogger? GetLogger() => logger;
public static IApplicationBuilder UseNpgsqlRest(this IApplicationBuilder builder, NpgsqlRestOptions options)
{
if (options.ConnectionString is null && options.ConnectionFromServiceProvider is false)
{
throw new ArgumentException("Connection string is null and ConnectionFromServiceProvider is false. Set the connection string or use ConnectionFromServiceProvider");
}

ILogger? logger = null;
if (options.Logger is not null)
{
logger = options.Logger;
Expand Down Expand Up @@ -529,7 +530,7 @@ public static IApplicationBuilder UseNpgsqlRest(this IApplicationBuilder builder
{
connection.Notice += (sender, args) =>
{
Logger.LogConnectionNotice(ref logger, ref args);
NpgsqlRestLogger.LogConnectionNotice(ref logger, ref args);
};
}
Expand Down Expand Up @@ -644,7 +645,7 @@ public static IApplicationBuilder UseNpgsqlRest(this IApplicationBuilder builder
if (shouldLog)
{
Logger.LogEndpoint(ref logger, ref endpoint, cmdLog?.ToString() ?? "", command.CommandText);
NpgsqlRestLogger.LogEndpoint(ref logger, ref endpoint, cmdLog?.ToString() ?? "", command.CommandText);
}
if (endpoint.CommandTimeout.HasValue)
Expand Down Expand Up @@ -915,7 +916,7 @@ public static IApplicationBuilder UseNpgsqlRest(this IApplicationBuilder builder
}
if (context.Response.StatusCode != 200 || context.Response.HasStarted)
{
logger?.LogError(exception, "Error executing command: {0} mapped to endpoint: {1}", commandText, endpoint.Url);
logger?.LogError(exception, "Error executing command: {commandText} mapped to endpoint: {Url}", commandText, endpoint.Url);
await context.Response.CompleteAsync();
return;
}
Expand Down
8 changes: 4 additions & 4 deletions NpgsqlRest/NpgsqlRest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageReadmeFile>README.MD</PackageReadmeFile>
<DocumentationFile>bin\$(Configuration)\$(AssemblyName).xml</DocumentationFile>
<Version>2.8.3</Version>
<AssemblyVersion>2.8.3</AssemblyVersion>
<FileVersion>2.8.3</FileVersion>
<PackageVersion>2.8.3</PackageVersion>
<Version>2.8.4</Version>
<AssemblyVersion>2.8.4</AssemblyVersion>
<FileVersion>2.8.4</FileVersion>
<PackageVersion>2.8.4</PackageVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
Expand Down
2 changes: 1 addition & 1 deletion NpgsqlRest/Logger.cs → NpgsqlRest/NpgsqlRestLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public static partial class Log
public static partial void InvalidBufferRows(this ILogger logger, string buffer, string schema, string name, ulong defaultBufferRows);
}

internal static class Logger
public static class NpgsqlRestLogger
{
private const string Info = "INFO";
private const string Notice = "NOTICE";
Expand Down
2 changes: 1 addition & 1 deletion NpgsqlRest/RoutineEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ public struct RoutineEndpoint(
public HashSet<string>? AuthorizeRoles { get; set; } = authorizeRoles;
public bool Login { get; set; } = login;
public bool Logout { get; set; } = logout;
public bool IsAuth => Login || Logout;
public readonly bool IsAuth => Login || Logout;
public ulong? BufferRows { get; set; } = bufferRows;
}
63 changes: 56 additions & 7 deletions NpgsqlRestClient/ExternalAuth.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using static NpgsqlRestClient.Config;
using static NpgsqlRestClient.Builder;
using static NpgsqlRest.Auth.ClaimsDictionary;
using Microsoft.AspNetCore.Routing;

namespace NpgsqlRestClient;

Expand All @@ -36,7 +37,7 @@ public static class ExternalAuthConfig
public static string ReturnToPath { get; private set; } = default!;
public static string ReturnToPathQueryStringKey { get; private set; } = default!;
public static string LoginCommand { get; private set; } = default!;
public static Dictionary<string, ExternalAuthClientConfig> ClientConfigs { get; private set; } = new();
public static Dictionary<string, ExternalAuthClientConfig> ClientConfigs { get; private set; } = [];

public static void Build(IConfigurationSection authConfig)
{
Expand Down Expand Up @@ -126,7 +127,7 @@ public static void Configure(WebApplication app, NpgsqlRestOptions options)
string code = (node["code"]?.ToString()) ??
throw new ArgumentException("code retrieved from the external provider is null");
await ProcessAsync(code, config, context, options);
await ProcessAsync(code, body, config, context, options);
return;
}
catch (Exception e)
Expand Down Expand Up @@ -158,7 +159,12 @@ void PrepareResponse(string contentType)
private const string browserSessionStateKey = "__external_state";
private const string browserSessionParamsKey = "__external_params";

private static async Task ProcessAsync(string code, ExternalAuthClientConfig config, HttpContext context, NpgsqlRestOptions options)
private static async Task ProcessAsync(
string code,
string body,
ExternalAuthClientConfig config,
HttpContext context,
NpgsqlRestOptions options)
{
string? email;
string? name;
Expand Down Expand Up @@ -265,18 +271,61 @@ private static async Task ProcessAsync(string code, ExternalAuthClientConfig con
throw new ArgumentException("email retrieved from the external provider is null");
}

var logger = NpgsqlRestMiddlewareExtensions.GetLogger();
using var connection = new NpgsqlConnection(options.ConnectionString);
if (options.LogConnectionNoticeEvents && logger != null)
{
connection.Notice += (sender, args) =>
{
NpgsqlRestLogger.LogConnectionNotice(ref logger, ref args);
};
}

await connection.OpenAsync();
using var command = connection.CreateCommand();
command.CommandText = ExternalAuthConfig.LoginCommand;
command.Parameters.Add(new NpgsqlParameter()
var paramCount = command.CommandText[command.CommandText.IndexOf('(')..].Split(',').Length;

if (paramCount >= 1) command.Parameters.Add(new NpgsqlParameter()
{
Value = email,
NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Text
});
command.Parameters.Add(new NpgsqlParameter()
if (paramCount >= 2) command.Parameters.Add(new NpgsqlParameter()
{
Value = name is not null ? name : DBNull.Value
Value = name is not null ? name : DBNull.Value,
NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Text
});
if (paramCount >= 3) command.Parameters.Add(new NpgsqlParameter()
{
Value = body is not null ? body : DBNull.Value,
NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Json
});

if (logger?.IsEnabled(LogLevel.Information) is true && options.LogCommands)
{
var commandToLog = command.CommandText;
if (options.LogCommandParameters)
{
StringBuilder paramsToLog = new();
for (var i = 0; i < command.Parameters.Count; i++)
{
var p = command.Parameters[i];
paramsToLog!.AppendLine(string.Concat(
"-- $",
(i + 1).ToString(),
" ", p.DataTypeName,
" = ",
p.Value));
}
logger?.Log(LogLevel.Information, "{paramsToLog}{commandToLog}", paramsToLog, commandToLog);
}
else
{
logger?.Log(LogLevel.Information, "{commandToLog}", commandToLog);
}
}

await using NpgsqlDataReader reader = await command.ExecuteReaderAsync();

if (await reader.ReadAsync() is false || reader.FieldCount == 0)
Expand Down Expand Up @@ -473,7 +522,7 @@ private static string GetRedirectUrl(ExternalAuthClientConfig clientConfig, Http
var externalType = "{9}";
var params = paramsToObject(window.location.search);
var keys = Object.keys(params);
if (keys.length==0 || (keys.length==1 && params[returnToPathQueryStringKey])) {{
if (!params.error && !params.state) {{
if (params[returnToPathQueryStringKey]) {{
sessionStorage.setItem(returnToKey, params[returnToPathQueryStringKey]);
delete params[returnToPathQueryStringKey];
Expand Down
2 changes: 1 addition & 1 deletion NpgsqlRestClient/NpgsqlRestClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<InvariantGlobalization>true</InvariantGlobalization>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<PublishAot>true</PublishAot>
<Version>1.2.5</Version>
<Version>1.2.7</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
3 changes: 1 addition & 2 deletions NpgsqlRestClient/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@
CustomRequestHeaders = GetCustomHeaders()
};

ExternalAuth.Configure(app, options);

app.UseNpgsqlRest(options);
ExternalAuth.Configure(app, options);
app.Run();
7 changes: 4 additions & 3 deletions NpgsqlRestClient/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,11 @@
"ReturnToPathQueryStringKey": "return_to",
//
// Login command to execute after the external auth process is completed.
// The first parameter is the email returned from the provider, the second parameter is the name is the email returned from the provider.
// The command uses the same rules as the login enabled routine. See: https://vb-consulting.github.io/npgsqlrest/login-endpoints
// The first parameter is the email returned from the provider, the second parameter is the name returned from the provider and third parameter is the collection of the parameters that will include original query string.
// The command uses the same rules as the login enabled routine.
// See: https://vb-consulting.github.io/npgsqlrest/login-endpoints and https://vb-consulting.github.io/npgsqlrest/login-endpoints/#external-logins
//
"LoginCommand": "select * from login($1, $2)",
"LoginCommand": "select * from external_login($1,$2,$3)",

"Google": {
//
Expand Down
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ Note: For a changelog for a client application [see the client application page

---

## Version [2.8.4](https://github.com/vb-consulting/NpgsqlRest/tree/2.8.4) (2024-06-22)

[Full Changelog](https://github.com/vb-consulting/NpgsqlRest/compare/2.8.3...2.8.4)

Slight improvements in logging and enabling it to work with the client application.

## Version [2.8.3](https://github.com/vb-consulting/NpgsqlRest/tree/2.8.3) (2024-06-11)

[Full Changelog](https://github.com/vb-consulting/NpgsqlRest/compare/2.8.2...2.8.3)
Expand Down
13 changes: 12 additions & 1 deletion client.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ Example: npgsqlrest appsettings.json -o appsetting

## Changelog

### Version 1.2.7

- Upgrade NpgsqlRest to 2.8.3.

- Version from 1.2.4 to 1.2.7 is to sync with the version of the NPM package.

- Improvements in external auth:
- The optional third parameter receives JSON with parameters received from an external provider and query string parameters supplied to the original endpoint.
- Login command number of parameters is optional i.e. it can be either `select * from auth($1)` or `select * from auth($1,$2)` or `select * from auth($1,$2,3)` (three is max).
- Calls to external login/auth commands are logged by the same options, same rules, same format and the same logger as all other commands.

### Version 1.2.4

- Upgrade NpgsqlRest to 2.8.2.
Expand All @@ -104,7 +115,7 @@ The `NpgsqlRest.InstanceIdRequestHeaderName` setting allows you to specify the h

This is useful when you have multiple instances of the application running behind a load balancer, and you want to identify which instance is handling the request.

Default is `null` (not used).
The default is `null`` (not used).

### Version 1.2.2

Expand Down
37 changes: 37 additions & 0 deletions login-endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,40 @@ Login
- Note: this message is only returned in a case when the configured authentication scheme doesn't write anything into the response body on a sign-in operation.

- For example, the Cookie authentication scheme doesn't write anything into the body and this message is safely written to the response body. On the other hand, the Bearer Token schemes will always write the response body and this message will not be written to the response body.

## External Logins

External logins are functionality from the client application. They are configured in the following configuration section:

```jsonc
{
//
// ...
//
"Auth": {
//
// ...
//
"External": {
//
// ...
//
"LoginCommand": "select * from external_login($1,$2,$3)",
//
// ...
//
}
}
}
```

See the [Client Application Default Config](https://vb-consulting.github.io/npgsqlrest/config/) for more info.

Return values from this command follow the same convention [described above](https://vb-consulting.github.io/npgsqlrest/login-endpoints/#login-endpoint-conventions).

This command can have up to three parameters maximum. The second and third parameters are optional. These are:

1) Email (text) received from the external provider.
2) Name (text) received from the external provider. If the external provider doesn't provide a name this is null.
3) Parameters (JSON). Includes a collection of parameter values received from the external provider, plus the original query strings if any (for example `/signin-google?param1=test`). This allows for different types of processing of external provider data (registration or just login for example).

2 changes: 1 addition & 1 deletion npm/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "npgsqlrest",
"version": "1.2.6",
"version": "1.2.7",
"description": "Automatic REST API for PostgreSQL Databases Client Build",
"scripts": {
"postinstall": "node postinstall.js",
Expand Down
2 changes: 1 addition & 1 deletion npm/postinstall.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const os = require("os");
const https = require("https");

const downloadDir = "../.bin/";
const downloadFrom = "https://github.com/vb-consulting/NpgsqlRest/releases/download/v2.8.3-client-v1.2.5/";
const downloadFrom = "https://github.com/vb-consulting/NpgsqlRest/releases/download/v2.8.4-client-v1.2.7/";

function download(url, to, done) {
https.get(url, (response) => {
Expand Down
20 changes: 20 additions & 0 deletions npm/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,26 @@ See the detailed change log:
- [NpgsqlRest Changelog](https://vb-consulting.github.io/npgsqlrest/changelog/)
- [NpgsqlRest Client Changelog](https://vb-consulting.github.io/npgsqlrest/client/#changelog)

### 1.2.7

```console
Versions:
Client Build 1.2.7.0
NpgsqlRest 2.8.4.0
NpgsqlRest.HttpFiles 1.0.2.0
NpgsqlRest.TsClient 1.8.1.0
```

### 1.2.6

```console
Versions:
Client Build 1.2.5.0
NpgsqlRest 2.8.3.0
NpgsqlRest.HttpFiles 1.0.2.0
NpgsqlRest.TsClient 1.8.1.0
```

### 1.2.5

```console
Expand Down

0 comments on commit 4eaebb0

Please sign in to comment.