This commit is contained in:
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -44,7 +44,7 @@
|
|||||||
//"AYANOVA_LOG_LEVEL": "Debug",
|
//"AYANOVA_LOG_LEVEL": "Debug",
|
||||||
"AYANOVA_DEFAULT_TRANSLATION": "en",
|
"AYANOVA_DEFAULT_TRANSLATION": "en",
|
||||||
//TRANSLATION MUST BE en for Integration TESTING
|
//TRANSLATION MUST BE en for Integration TESTING
|
||||||
//"AYANOVA_PERMANENTLY_ERASE_DATABASE": "true",
|
"AYANOVA_PERMANENTLY_ERASE_DATABASE": "true",
|
||||||
"AYANOVA_DB_CONNECTION": "Server=localhost;Username=postgres;Password=raven;Database=AyaNova;",
|
"AYANOVA_DB_CONNECTION": "Server=localhost;Username=postgres;Password=raven;Database=AyaNova;",
|
||||||
"AYANOVA_USE_URLS": "http://*:7575;",
|
"AYANOVA_USE_URLS": "http://*:7575;",
|
||||||
"AYANOVA_FOLDER_USER_FILES": "c:\\temp\\RavenTestData\\userfiles",
|
"AYANOVA_FOLDER_USER_FILES": "c:\\temp\\RavenTestData\\userfiles",
|
||||||
|
|||||||
@@ -71,6 +71,11 @@ todo: RAVEN new job LicenseCheck
|
|||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
|
|
||||||
|
todo: authentication login from IP address, it should really be an option or kept where it can be viewed but not overwhelm the log file
|
||||||
|
Maybe a switch to disable or mask it or fully enable so "AY_LOG_LOGIN" values "FULL" or "MASK" or "DEBUG_FULL" or "DEBUG_MASK" or "NONE"
|
||||||
|
Defaults to FULL
|
||||||
|
|
||||||
todo: permanently erase db startup thing, should it really exist?
|
todo: permanently erase db startup thing, should it really exist?
|
||||||
It will zap the dbid so a user might expect to just use their old license but it wont' fetch again
|
It will zap the dbid so a user might expect to just use their old license but it wont' fetch again
|
||||||
we could issue a new key to replace with the new dbid and also issue a revoke key for the old dbid so that
|
we could issue a new key to replace with the new dbid and also issue a revoke key for the old dbid so that
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace AyaNova.Api.Controllers
|
|||||||
|
|
||||||
|
|
||||||
if (serverState.IsClosed && AyaNova.Core.License.ActiveKey.KeyDoesNotNeedAttention)
|
if (serverState.IsClosed && AyaNova.Core.License.ActiveKey.KeyDoesNotNeedAttention)
|
||||||
{
|
{
|
||||||
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
|
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,11 +169,13 @@ namespace AyaNova.Api.Controllers
|
|||||||
//check if server closed
|
//check if server closed
|
||||||
//if it is it means we got here only because there is no license
|
//if it is it means we got here only because there is no license
|
||||||
//and only *the* SuperUser account can login now
|
//and only *the* SuperUser account can login now
|
||||||
if(serverState.IsClosed){
|
if (serverState.IsClosed)
|
||||||
|
{
|
||||||
//if not SuperUser account then boot closed
|
//if not SuperUser account then boot closed
|
||||||
//SuperUser account is always ID 1
|
//SuperUser account is always ID 1
|
||||||
if(u.Id!=1){
|
if (u.Id != 1)
|
||||||
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
{
|
||||||
|
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Restrict auth due to server state?
|
//Restrict auth due to server state?
|
||||||
@@ -222,9 +224,16 @@ namespace AyaNova.Api.Controllers
|
|||||||
|
|
||||||
//save auth token to ensure single sign on only
|
//save auth token to ensure single sign on only
|
||||||
u.CurrentAuthToken = token;
|
u.CurrentAuthToken = token;
|
||||||
|
|
||||||
|
u.LastLogin = DateTime.UtcNow;
|
||||||
|
|
||||||
await ct.SaveChangesAsync();
|
await ct.SaveChangesAsync();
|
||||||
|
|
||||||
log.LogDebug($"User number \"{u.Id}\" logged in from \"{Util.StringUtil.MaskIPAddress(HttpContext.Connection.RemoteIpAddress.ToString())}\" ok");
|
//KEEP this, masked version of IP address
|
||||||
|
//Not sure if this is necessary or not but if it turns out to be then make it a boot option
|
||||||
|
// log.LogInformation($"User number \"{u.Id}\" logged in from \"{Util.StringUtil.MaskIPAddress(HttpContext.Connection.RemoteIpAddress.ToString())}\" ok");
|
||||||
|
|
||||||
|
log.LogInformation($"User \"{u.Name}\" logged in from \"{HttpContext.Connection.RemoteIpAddress.ToString()}\" ok");
|
||||||
|
|
||||||
|
|
||||||
return Ok(ApiOkResponse.Response(new
|
return Ok(ApiOkResponse.Response(new
|
||||||
|
|||||||
@@ -40,6 +40,20 @@ namespace AyaNova.Biz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Called by license processor when use downgrades to lesser amount of techs
|
||||||
|
internal static async Task DeActivateExcessiveTechs(int KeepThisManyActiveTechs)
|
||||||
|
{
|
||||||
|
using (AyContext ct = ServiceProviderProvider.DBContext)
|
||||||
|
{
|
||||||
|
var ActiveTechList = await ct.User.AsNoTracking().Where(z => z.Active == true && (
|
||||||
|
z.UserType == UserType.Service ||
|
||||||
|
z.UserType == UserType.ServiceContractor)).ToListAsync();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
internal static UserBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null)
|
internal static UserBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null)
|
||||||
{
|
{
|
||||||
if (httpContext != null)
|
if (httpContext != null)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace AyaNova.Models
|
|||||||
public dtUser()
|
public dtUser()
|
||||||
{
|
{
|
||||||
Tags = new List<string>();
|
Tags = new List<string>();
|
||||||
|
LastLogin = DateTime.MinValue;
|
||||||
}
|
}
|
||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
public uint Concurrency { get; set; }
|
public uint Concurrency { get; set; }
|
||||||
@@ -27,6 +28,8 @@ namespace AyaNova.Models
|
|||||||
public string Wiki { get; set; }
|
public string Wiki { get; set; }
|
||||||
public string CustomFields { get; set; }
|
public string CustomFields { get; set; }
|
||||||
public List<string> Tags { get; set; }
|
public List<string> Tags { get; set; }
|
||||||
|
|
||||||
|
public DateTime LastLogin { get; set; }
|
||||||
}//eoc
|
}//eoc
|
||||||
|
|
||||||
public class User : ICoreBizObjectModel
|
public class User : ICoreBizObjectModel
|
||||||
@@ -39,6 +42,8 @@ namespace AyaNova.Models
|
|||||||
[Required, MaxLength(255)]
|
[Required, MaxLength(255)]
|
||||||
public string Name { get; set; }
|
public string Name { 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; }
|
||||||
|
|
||||||
|
|||||||
@@ -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 = 11;
|
private const int DESIRED_SCHEMA_LEVEL = 11;
|
||||||
|
|
||||||
internal const long EXPECTED_COLUMN_COUNT = 324;
|
internal const long EXPECTED_COLUMN_COUNT = 325;
|
||||||
internal const long EXPECTED_INDEX_COUNT = 134;
|
internal const long EXPECTED_INDEX_COUNT = 134;
|
||||||
|
|
||||||
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
||||||
@@ -325,7 +325,7 @@ $BODY$;
|
|||||||
|
|
||||||
//Add user table
|
//Add user table
|
||||||
await ExecQueryAsync("CREATE TABLE auser (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, active bool not null, name varchar(255) not null unique, " +
|
await ExecQueryAsync("CREATE TABLE auser (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, active bool not null, name varchar(255) not null unique, " +
|
||||||
"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, usertype integer not null, employeenumber varchar(255), notes text, customerid bigint, " +
|
"dlkey text, dlkeyexpire timestamp, usertype integer not null, employeenumber varchar(255), notes text, customerid bigint, " +
|
||||||
"headofficeid bigint, subvendorid bigint, wiki text null, customfields text, tags varchar(255) ARRAY)");
|
"headofficeid bigint, subvendorid bigint, wiki text null, customfields text, tags varchar(255) ARRAY)");
|
||||||
|
|
||||||
|
|||||||
@@ -707,6 +707,9 @@ namespace AyaNova.Core
|
|||||||
//TODO: TECHCOUNT - new license causes exceeding count?
|
//TODO: TECHCOUNT - new license causes exceeding count?
|
||||||
if (await AyaNova.Biz.UserBiz.ActiveCountAsync() > ParsedNewKey.GetLicenseFeature(SERVICE_TECHS_FEATURE_NAME).Count)
|
if (await AyaNova.Biz.UserBiz.ActiveCountAsync() > ParsedNewKey.GetLicenseFeature(SERVICE_TECHS_FEATURE_NAME).Count)
|
||||||
{
|
{
|
||||||
|
//Ok, the easy thing to do here is just set all techs inactive, but
|
||||||
|
//a trickier but probably better thing to do is set just enough techs inactive and choose them based
|
||||||
|
//on the oldest last login datetime first
|
||||||
throw new ApplicationException("E1020 - Can't install key, too many active techs and / or subcontractors in database. Deactivate enough to install key.");
|
throw new ApplicationException("E1020 - Can't install key, too many active techs and / or subcontractors in database. Deactivate enough to install key.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user