diff --git a/server/AyaNova/biz/UserBiz.cs b/server/AyaNova/biz/UserBiz.cs index 391717c6..ebd79d7a 100644 --- a/server/AyaNova/biz/UserBiz.cs +++ b/server/AyaNova/biz/UserBiz.cs @@ -43,6 +43,8 @@ namespace AyaNova.Biz using (AyContext ct = ServiceProviderProvider.DBContext) { //all users who are not the superuser, active and not a customer or headoffice + //NOTE: AllowLogin is not counted here like it is with a Customer login account, we don't care, active is all that matters for license + //consumption var ret = await ct.User.AsNoTracking().Where(z => z.Id != 1 && z.Active == true && ( z.UserType != UserType.Customer && z.UserType != UserType.HeadOffice)).LongCountAsync(); @@ -75,6 +77,48 @@ namespace AyaNova.Biz } } + + + + //Called by license processor in case customer has downgraded the number of internal user licenses so that key install doesn't fail + internal static async Task DeActivateExcessiveInternallUsers(long KeepThisManyActiveInternalUsers, ILogger _log) + { + //case 4578 several modifications to this from prior existing function before switching to license by any internal users not just tech + var TotalActiveInternalUsers = await ActiveInternalUserCountAsync(); + int CountOfUsersToSetInactive = (int)(TotalActiveInternalUsers - KeepThisManyActiveInternalUsers); + if (CountOfUsersToSetInactive < 1) return; + _log.LogInformation($"New license is a downgrade with fewer Users - deactivating {CountOfUsersToSetInactive} least recently logged in Users automatically so the license can be installed"); + using (AyContext ct = ServiceProviderProvider.DBContext) + { + + //Algorithm: For deactivation favor ones that have no login records and finally favor by oldest last login + //theory is to catch the least likely to be currently active user so least affected + + var InsideUserCanLoginByLastLoginList = await ct.User.Where(z => z.Active == true && ( + z.UserType != UserType.Customer && + z.UserType != UserType.HeadOffice)).OrderByDescending(z => z.LastLogin).Take(CountOfUsersToSetInactive).ToListAsync(); + + //TODO: examine this list, is it correct and in correct order + + CountOfUsersToSetInactive -= InsideUserCanLoginByLastLoginList.Count(); + foreach (User u in InsideUserCanLoginByLastLoginList) + { + u.Active = false; + var msg = $"User {u.Name} automatically set to inactive accomodate downgraded User count license"; + await NotifyEventHelper.AddOpsProblemEvent(msg); + _log.LogInformation(msg); + } + await ct.SaveChangesAsync(); + + #if (SUBSCRIPTION_BUILD) + //Customer users as above + #endif + + } + } + + + // //Called by license processor when use downgrades to lesser amount of techs // internal static async Task DeActivateExcessiveTechs(long KeepThisManyActiveTechs, ILogger _log) // { diff --git a/server/AyaNova/util/License.cs b/server/AyaNova/util/License.cs index 7b8cf232..843d91b8 100644 --- a/server/AyaNova/util/License.cs +++ b/server/AyaNova/util/License.cs @@ -862,60 +862,33 @@ namespace AyaNova.Core } + //DOWNGRADE LICENSE? //Only check quantities if it's not a revoke token which should always pass through if (ParsedNewKey.RegisteredTo != REVOKED_TOKEN) { + + //case 4578 automatically disable excess internal users + await AyaNova.Biz.UserBiz.DeActivateExcessiveInternallUsers(ParsedNewKey.ActiveInternalUsersCount, log); + + #if (SUBSCRIPTION_BUILD) + //case 4578 handles internal user count adjustment to match license in downgrade automatically + //but it can't handle customer login downgrade as that might fuck up the business badly if suddenly a bunch of random customers can't login so *they* would need to handle that themselves manually + //so keeping that bit of code here - //SUBSCRIPTION USER COUNTS - new license causes exceeding counts? - - long NewInsideUserLicensedCount = ParsedNewKey.ActiveInternalUsersCount; - long ExistingActiveInsideUserCount = await AyaNova.Biz.UserBiz.ActiveInternalUserCountAsync(); + //SUBSCRIPTION CUSTOMER LOGIN ACCOUNT QUANTITY DOWNGRADED? long NewCustomerLicensedCount = ParsedNewKey.ActiveCustomerContactUsersCount; long ExistingCustomerUserCount = await AyaNova.Biz.UserBiz.ActiveCustomerContactUserCountAsync(); string err = "E1020 - Can't install license: "; bool throwit = false; - if (ExistingActiveInsideUserCount > NewInsideUserLicensedCount) - { - throwit = true; - err += $"{ExistingActiveInsideUserCount} active internal users of {NewInsideUserLicensedCount} permitted"; - } - if (ExistingCustomerUserCount > NewCustomerLicensedCount) { throwit = true; err += $"{ExistingCustomerUserCount} active Customer login users of {NewCustomerLicensedCount} permitted"; } - if (throwit) throw new ApplicationException(err); - -#else - //PERPETUAL, vet the TECHCOUNT - new license causes exceeding count? - // long NewTechCount = ParsedNewKey.ActiveTechsCount; - // if (await AyaNova.Biz.UserBiz.ActiveTechUserCountAsync() > NewTechCount) - // { - // //attempt to set enough of the eldest last login techs to inactive - // await AyaNova.Biz.UserBiz.DeActivateExcessiveTechs(NewTechCount, log); - - // if (await AyaNova.Biz.UserBiz.ActiveTechUserCountAsync() > NewTechCount) - // throw new ApplicationException("E1020 - Can't install key, too many active techs and / or subcontractors in database. Deactivate enough to install key."); - // } - - long NewInsideUserLicensedCount = ParsedNewKey.ActiveInternalUsersCount; - long ExistingActiveInsideUserCount = await AyaNova.Biz.UserBiz.ActiveInternalUserCountAsync(); - - string err = "E1020 - Can't install license: "; - bool throwit = false; - if (ExistingActiveInsideUserCount > NewInsideUserLicensedCount) - { - throwit = true; - err += $"{ExistingActiveInsideUserCount} active internal users of {NewInsideUserLicensedCount} permitted"; - } - - if (throwit) - throw new ApplicationException(err); #endif }