This commit is contained in:
2020-05-02 19:24:47 +00:00
parent 9df1252cd6
commit 64f4314015
7 changed files with 52 additions and 10 deletions

View File

@@ -86,6 +86,7 @@ namespace AyaNova.Api.Controllers
/// <summary> /// <summary>
/// Put (update) User /// Put (update) User
/// (Login and / or Password are not changed if set to null / omitted)
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <param name="inObj"></param> /// <param name="inObj"></param>

View File

@@ -432,7 +432,7 @@ namespace AyaNova.Biz
//throw new System.ArgumentException("BizRoles::Constructor - roles were modified from last snapshot for client!!!"); //throw new System.ArgumentException("BizRoles::Constructor - roles were modified from last snapshot for client!!!");
// log = // log =
{ {
((ILogger)AyaNova.Util.ApplicationLogging.CreateLogger("BizRoles.cs")).LogError("BizRoles::Constructor - roles were modified from last snapshot for client!!!"); ((ILogger)AyaNova.Util.ApplicationLogging.CreateLogger("BizRoles.cs")).LogWarning("BizRoles::Constructor - roles were modified from last snapshot for client!!!");
} }
} }

View File

@@ -49,6 +49,19 @@ namespace AyaNova.Biz
//CREATE //CREATE
internal async Task<User> CreateAsync(User inObj) internal async Task<User> CreateAsync(User inObj)
{ {
//password and login are optional but in the sense that they can be left out in a PUT
// but if left out here we need to generate a random value instead so they can't login but the code is happy
//because a login name and password are required always
if (string.IsNullOrWhiteSpace(inObj.Password))
{
inObj.Password = Hasher.GenerateSalt();//set it to some big random value
}
if (string.IsNullOrWhiteSpace(inObj.Login))
{
inObj.Login = Hasher.GenerateSalt();//set it to some big random value
}
//This is a new user so it will have been posted with a password in plaintext which needs to be salted and hashed //This is a new user so it will have been posted with a password in plaintext which needs to be salted and hashed
inObj.Salt = Hasher.GenerateSalt(); inObj.Salt = Hasher.GenerateSalt();
inObj.Password = Hasher.hash(inObj.Salt, inObj.Password); inObj.Password = Hasher.hash(inObj.Salt, inObj.Password);
@@ -88,6 +101,10 @@ namespace AyaNova.Biz
//TAGS //TAGS
await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, inObj.Tags, null); await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, inObj.Tags, null);
//Accept, but never return a User's password or login
inObj.Password = null;
inObj.Login = null;
return inObj; return inObj;
} }
@@ -128,6 +145,7 @@ namespace AyaNova.Biz
dbObj.Tags = TagUtil.NormalizeTags(dbObj.Tags); dbObj.Tags = TagUtil.NormalizeTags(dbObj.Tags);
dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields); dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields);
//NOTE: It's valid to call this without intending to change login or password (null values)
//Is the user updating the password? //Is the user updating the password?
if (!string.IsNullOrWhiteSpace(inObj.Password) && SnapshotOfOriginalDBObj.Password != inObj.Password) if (!string.IsNullOrWhiteSpace(inObj.Password) && SnapshotOfOriginalDBObj.Password != inObj.Password)
{ {
@@ -140,6 +158,17 @@ namespace AyaNova.Biz
dbObj.Password = SnapshotOfOriginalDBObj.Password; dbObj.Password = SnapshotOfOriginalDBObj.Password;
dbObj.Salt = SnapshotOfOriginalDBObj.Salt; dbObj.Salt = SnapshotOfOriginalDBObj.Salt;
} }
//Updating login?
if (!string.IsNullOrWhiteSpace(inObj.Login))
{
//YES Login is being updated:
dbObj.Login=inObj.Login;
}
else
{
//No, use the original value
dbObj.Login = SnapshotOfOriginalDBObj.Login;
}
//Set "original" value of concurrency token to input token //Set "original" value of concurrency token to input token
@@ -183,6 +212,18 @@ namespace AyaNova.Biz
dbObj.Password = Hasher.hash(dbObj.Salt, dbObj.Password); dbObj.Password = Hasher.hash(dbObj.Salt, dbObj.Password);
} }
//Updating login?
if (!string.IsNullOrWhiteSpace(dbObj.Login) && dbObj.Login != SnapshotOfOriginalDBObj.Login)
{
//YES Login is being updated:
dbObj.Login=SnapshotOfOriginalDBObj.Login;
}
else
{
//No, use the original value
dbObj.Login = SnapshotOfOriginalDBObj.Login;
}
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = concurrencyToken; ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = concurrencyToken;
await ValidateAsync(dbObj, SnapshotOfOriginalDBObj); await ValidateAsync(dbObj, SnapshotOfOriginalDBObj);
if (HasErrors) if (HasErrors)

View File

@@ -5,11 +5,13 @@ namespace AyaNova.Models
{ {
public partial class AyContext : DbContext public partial class AyContext : DbContext
{ {
public virtual DbSet<User> User { get; set; }
public virtual DbSet<UserOptions> UserOptions { get; set; }
public virtual DbSet<Widget> Widget { get; set; } public virtual DbSet<Widget> Widget { get; set; }
public virtual DbSet<GlobalBizSettings> GlobalBizSettings { get; set; } public virtual DbSet<GlobalBizSettings> GlobalBizSettings { get; set; }
public virtual DbSet<Event> Event { get; set; } public virtual DbSet<Event> Event { get; set; }
public virtual DbSet<SearchDictionary> SearchDictionary { get; set; } public virtual DbSet<SearchDictionary> SearchDictionary { get; set; }
public virtual DbSet<SearchKey> SearchKey { get; set; } public virtual DbSet<SearchKey> SearchKey { get; set; }
public virtual DbSet<FileAttachment> FileAttachment { get; set; } public virtual DbSet<FileAttachment> FileAttachment { get; set; }
public virtual DbSet<OpsJob> OpsJob { get; set; } public virtual DbSet<OpsJob> OpsJob { get; set; }
public virtual DbSet<OpsJobLog> OpsJobLog { get; set; } public virtual DbSet<OpsJobLog> OpsJobLog { get; set; }
@@ -19,8 +21,6 @@ namespace AyaNova.Models
public virtual DbSet<Tag> Tag { get; set; } public virtual DbSet<Tag> Tag { get; set; }
public virtual DbSet<FormCustom> FormCustom { get; set; } public virtual DbSet<FormCustom> FormCustom { get; set; }
public virtual DbSet<PickListTemplate> PickListTemplate { get; set; } public virtual DbSet<PickListTemplate> PickListTemplate { get; set; }
public virtual DbSet<User> User { get; set; }
public virtual DbSet<UserOptions> UserOptions { get; set; }
public virtual DbSet<License> License { get; set; } public virtual DbSet<License> License { get; set; }
public virtual DbSet<Customer> Customer { get; set; } public virtual DbSet<Customer> Customer { get; set; }
public virtual DbSet<Contract> Contract { get; set; } public virtual DbSet<Contract> Contract { get; set; }

View File

@@ -15,9 +15,9 @@ namespace AyaNova.Models
public bool Active { get; set; } public bool Active { get; set; }
[Required, MaxLength(255)] [Required, MaxLength(255)]
public string Name { get; set; } public string Name { get; set; }
[Required] //[Required]
public string Login { get; set; } public string Login { get; set; }
[Required] //[Required]
public string Password { get; set; } public string Password { get; set; }
public string Salt { get; set; } public string Salt { get; set; }
[Required] [Required]

View File

@@ -181,7 +181,7 @@ namespace AyaNova.Util
await ExecQueryAsync("CREATE TABLE auseroptions (id BIGSERIAL PRIMARY KEY, " + await ExecQueryAsync("CREATE TABLE auseroptions (id BIGSERIAL PRIMARY KEY, " +
"userid bigint not null, translationid bigint not null REFERENCES atranslation (id), languageoverride text, timezoneoverride text, currencyname text, hour12 bool not null, emailaddress text, uicolor varchar(12) not null default '#000000')"); "userid bigint not null, translationid bigint not null REFERENCES atranslation (id), languageoverride text, timezoneoverride text, currencyname text, hour12 bool not null, emailaddress text, uicolor varchar(12) not null default '#000000')");
//Prime the db with the default MANAGER account //Prime the db with the default MANAGER account
await AyaNova.Biz.PrimeData.PrimeManagerAccount(ct); await AyaNova.Biz.PrimeData.PrimeManagerAccount(ct);
@@ -454,7 +454,7 @@ namespace AyaNova.Util
await ExecQueryAsync("CREATE UNIQUE INDEX apmtemplateitem_name_id_idx ON apmtemplateitem (id, name);"); await ExecQueryAsync("CREATE UNIQUE INDEX apmtemplateitem_name_id_idx ON apmtemplateitem (id, name);");
await ExecQueryAsync("CREATE INDEX apmtemplateitem_tags ON apmtemplateitem using GIN(tags)"); await ExecQueryAsync("CREATE INDEX apmtemplateitem_tags ON apmtemplateitem using GIN(tags)");
await SetSchemaLevelAsync(++currentSchema); await SetSchemaLevelAsync(++currentSchema);
} }

View File

@@ -293,7 +293,7 @@ namespace AyaNova.Util
//REMOVE ALL DATA with few exceptions of manager user, license, schema tables //REMOVE ALL DATA with few exceptions of manager user, license, schema tables
//and job logs because this is called by job code //and job logs because this is called by job code
await EraseTableAsync("atranslationitem", conn); await EraseTableAsync("atranslationitem", conn);
await EraseTableAsync("atranslation", conn); await EraseTableAsync("atranslation", conn);
//Load the default TRANSLATIONS //Load the default TRANSLATIONS
@@ -353,7 +353,7 @@ namespace AyaNova.Util
using (var cmd = new Npgsql.NpgsqlCommand()) using (var cmd = new Npgsql.NpgsqlCommand())
{ {
cmd.Connection = conn; cmd.Connection = conn;
cmd.CommandText = "TRUNCATE \"" + sTable + "\" RESTART IDENTITY CASCADE;"; cmd.CommandText = "TRUNCATE \"" + sTable + "\" RESTART IDENTITY;";
await cmd.ExecuteNonQueryAsync(); await cmd.ExecuteNonQueryAsync();
} }
} }