This commit is contained in:
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -53,7 +53,7 @@
|
|||||||
"AYANOVA_FOLDER_USER_FILES": "c:\\temp\\RavenTestData\\userfiles",
|
"AYANOVA_FOLDER_USER_FILES": "c:\\temp\\RavenTestData\\userfiles",
|
||||||
"AYANOVA_FOLDER_BACKUP_FILES": "c:\\temp\\RavenTestData\\backupfiles",
|
"AYANOVA_FOLDER_BACKUP_FILES": "c:\\temp\\RavenTestData\\backupfiles",
|
||||||
"AYANOVA_FOLDER_TEMPORARY_SERVER_FILES": "c:\\temp\\RavenTestData\\tempfiles",
|
"AYANOVA_FOLDER_TEMPORARY_SERVER_FILES": "c:\\temp\\RavenTestData\\tempfiles",
|
||||||
"AYANOVA_SERVER_TEST_MODE": "true",
|
"AYANOVA_SERVER_TEST_MODE": "false",
|
||||||
"AYANOVA_SERVER_TEST_MODE_SEEDLEVEL": "small",
|
"AYANOVA_SERVER_TEST_MODE_SEEDLEVEL": "small",
|
||||||
"AYANOVA_SERVER_TEST_MODE_TZ_OFFSET": "-7",
|
"AYANOVA_SERVER_TEST_MODE_TZ_OFFSET": "-7",
|
||||||
"AYANOVA_BACKUP_PG_DUMP_PATH": "C:\\data\\code\\postgres_13\\bin\\"
|
"AYANOVA_BACKUP_PG_DUMP_PATH": "C:\\data\\code\\postgres_13\\bin\\"
|
||||||
|
|||||||
@@ -38,11 +38,13 @@
|
|||||||
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.3" />
|
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.3" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.1" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.1" />
|
||||||
<PackageReference Include="PuppeteerSharp" Version="2.0.4" />
|
<PackageReference Include="PuppeteerSharp" Version="2.0.4" />
|
||||||
|
<PackageReference Include="QRCoder" Version="1.4.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="5.6.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="5.6.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="5.6.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="5.6.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.6.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.6.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="5.6.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="5.6.3" />
|
||||||
|
<PackageReference Include="TwoFactorAuth.Net" Version="1.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using TwoFactorAuthNet;
|
||||||
|
using QRCoder;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using AyaNova.Models;
|
using AyaNova.Models;
|
||||||
@@ -424,6 +426,46 @@ namespace AyaNova.Api.Controllers
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate HOTP secret and return for use in auth app
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="apiVersion">From route path</param>
|
||||||
|
/// <returns>New HOTP secret</returns>
|
||||||
|
[HttpGet("hotp")]
|
||||||
|
public async Task<IActionResult> GenerateAndSendHOTP(ApiVersion apiVersion)
|
||||||
|
{
|
||||||
|
if (!serverState.IsOpen)
|
||||||
|
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||||
|
UserBiz biz = UserBiz.GetBiz(ct, HttpContext);
|
||||||
|
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
return BadRequest(new ApiErrorResponse(ModelState));
|
||||||
|
|
||||||
|
//get user and save the secret
|
||||||
|
var UserId = UserIdFromContext.Id(HttpContext.Items);
|
||||||
|
|
||||||
|
var u = await ct.User.FirstOrDefaultAsync(z => z.Id == UserId);
|
||||||
|
if (u == null)//should never happen but ?
|
||||||
|
return StatusCode(403, new ApiNotAuthorizedResponse());
|
||||||
|
|
||||||
|
var tfa = new TwoFactorAuth("AyaNova");
|
||||||
|
u.HotpSecret = tfa.CreateSecret(160);
|
||||||
|
await ct.SaveChangesAsync();
|
||||||
|
|
||||||
|
|
||||||
|
QRCodeGenerator qrGenerator = new QRCodeGenerator();
|
||||||
|
QRCodeData qrCodeData = qrGenerator.CreateQrCode(u.HotpSecret, QRCodeGenerator.ECCLevel.Q);
|
||||||
|
Base64QRCode qrCode = new Base64QRCode(qrCodeData);
|
||||||
|
string qrCodeImageAsBase64 = qrCode.GetGraphic(20);
|
||||||
|
|
||||||
|
return Ok(ApiOkResponse.Response(new
|
||||||
|
{
|
||||||
|
s = u.HotpSecret,
|
||||||
|
qrCode = qrCodeImageAsBase64
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
|
|
||||||
public class CredentialsParam
|
public class CredentialsParam
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ namespace AyaNova.Models
|
|||||||
public DateTime? LastLogin { get; set; }
|
public DateTime? LastLogin { get; set; }
|
||||||
public string Login { get; set; }
|
public string Login { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
public bool TwoFactorEnabled {get;set;}
|
||||||
[Required]
|
[Required]
|
||||||
public AuthorizationRoles Roles { get; set; }
|
public AuthorizationRoles Roles { get; set; }
|
||||||
[Required]
|
[Required]
|
||||||
@@ -95,6 +96,8 @@ namespace AyaNova.Models
|
|||||||
public string PasswordResetCode { get; set; }//---
|
public string PasswordResetCode { get; set; }//---
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public DateTime? PasswordResetCodeExpire { get; set; }//---
|
public DateTime? PasswordResetCodeExpire { get; set; }//---
|
||||||
|
[JsonIgnore]
|
||||||
|
public string HotpSecret { get; set; }//---
|
||||||
//==========================
|
//==========================
|
||||||
|
|
||||||
//relations
|
//relations
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace AyaNova.Util
|
|||||||
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
||||||
private const int DESIRED_SCHEMA_LEVEL = 15;
|
private const int DESIRED_SCHEMA_LEVEL = 15;
|
||||||
|
|
||||||
internal const long EXPECTED_COLUMN_COUNT = 788;
|
internal const long EXPECTED_COLUMN_COUNT = 790;
|
||||||
internal const long EXPECTED_INDEX_COUNT = 130;
|
internal const long EXPECTED_INDEX_COUNT = 130;
|
||||||
internal const long EXPECTED_CHECK_CONSTRAINTS = 359;
|
internal const long EXPECTED_CHECK_CONSTRAINTS = 359;
|
||||||
internal const long EXPECTED_FOREIGN_KEY_CONSTRAINTS = 78;
|
internal const long EXPECTED_FOREIGN_KEY_CONSTRAINTS = 78;
|
||||||
@@ -441,7 +441,8 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
|
|||||||
//Add user table
|
//Add user table
|
||||||
await ExecQueryAsync("CREATE TABLE auser (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, active BOOL NOT NULL, name TEXT NOT NULL UNIQUE, "
|
await ExecQueryAsync("CREATE TABLE auser (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, active BOOL NOT NULL, name TEXT NOT NULL UNIQUE, "
|
||||||
+ "lastlogin TIMESTAMP, login TEXT NOT NULL UNIQUE, password TEXT NOT NULL, salt TEXT NOT NULL, roles INTEGER NOT NULL, currentauthtoken TEXT, "
|
+ "lastlogin TIMESTAMP, login TEXT NOT NULL UNIQUE, password TEXT NOT NULL, salt TEXT NOT NULL, roles INTEGER NOT NULL, currentauthtoken TEXT, "
|
||||||
+ "dlkey TEXT, dlkeyexpire TIMESTAMP, passwordresetcode TEXT, passwordresetcodeexpire TIMESTAMP, usertype INTEGER NOT NULL, employeenumber TEXT, notes TEXT, customerid BIGINT, "
|
+ "dlkey TEXT, dlkeyexpire TIMESTAMP, hotpsecret TEXT, twofactorenabled BOOL, passwordresetcode TEXT, passwordresetcodeexpire TIMESTAMP, usertype INTEGER NOT NULL, "
|
||||||
|
+ "employeenumber TEXT, notes TEXT, customerid BIGINT, "
|
||||||
+ "headofficeid BIGINT, vendorid BIGINT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY)");
|
+ "headofficeid BIGINT, vendorid BIGINT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY)");
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user