This commit is contained in:
69
AyaNovaQBI/AuthorizationRoles.cs
Normal file
69
AyaNovaQBI/AuthorizationRoles.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AyaNovaQBI
|
||||
{
|
||||
/// <summary>
|
||||
/// Authorization roles
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum AuthorizationRoles : int
|
||||
{
|
||||
//https://stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c
|
||||
//MAX 31 (2147483647)!!! or will overflow int and needs to be turned into a long
|
||||
//Must be a power of two: https://en.wikipedia.org/wiki/Power_of_two
|
||||
|
||||
///<summary>No role set</summary>
|
||||
NoRole = 0,
|
||||
///<summary>BizAdminRestricted</summary>
|
||||
BizAdminRestricted = 1,
|
||||
///<summary>BizAdmin</summary>
|
||||
BizAdmin = 2,
|
||||
///<summary>ServiceRestricted</summary>
|
||||
ServiceRestricted = 4,
|
||||
///<summary>Service</summary>
|
||||
Service = 8,
|
||||
///<summary>InventoryRestricted</summary>
|
||||
InventoryRestricted = 16,
|
||||
///<summary>Inventory</summary>
|
||||
Inventory = 32,
|
||||
///<summary>Accounting</summary>
|
||||
Accounting = 64,//No limited role, not sure if there is a need
|
||||
///<summary>TechRestricted</summary>
|
||||
TechRestricted = 128,
|
||||
///<summary>Tech</summary>
|
||||
Tech = 256,
|
||||
///<summary>SubContractorRestricted</summary>
|
||||
SubContractorRestricted = 512, //same as tech but restricted by further business rules (more fine grained)
|
||||
///<summary>SubContractor</summary>
|
||||
SubContractor = 1024,//same as tech limited but restricted by further business rules (more fine grained)
|
||||
///<summary>ClientRestricted</summary>
|
||||
CustomerRestricted = 2048,
|
||||
///<summary>Client</summary>
|
||||
Customer = 4096,
|
||||
///<summary>OpsAdminRestricted</summary>
|
||||
OpsAdminRestricted = 8192,
|
||||
///<summary>OpsAdmin</summary>
|
||||
OpsAdmin = 16384,
|
||||
///<summary>Sales</summary>
|
||||
Sales = 32768,
|
||||
///<summary>SalesRestricted</summary>
|
||||
SalesRestricted = 65536,
|
||||
|
||||
|
||||
///<summary>Anyone of any role</summary>
|
||||
All = BizAdminRestricted | BizAdmin | ServiceRestricted | Service | InventoryRestricted |
|
||||
Inventory | Accounting | TechRestricted | Tech | SubContractorRestricted |
|
||||
SubContractor | CustomerRestricted | Customer | OpsAdminRestricted | OpsAdmin | Sales | SalesRestricted
|
||||
|
||||
// ,AllInsideUserRoles = BizAdminRestricted | BizAdmin | ServiceRestricted | Service | InventoryRestricted |
|
||||
// Inventory | Accounting | TechRestricted | Tech | SubContractorRestricted |
|
||||
// SubContractor | Sales | SalesRestricted | OpsAdminRestricted | OpsAdmin
|
||||
|
||||
|
||||
|
||||
}//end AuthorizationRoles
|
||||
}
|
||||
@@ -75,6 +75,7 @@
|
||||
<Compile Include="auth.Designer.cs">
|
||||
<DependentUpon>auth.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="AuthorizationRoles.cs" />
|
||||
<Compile Include="MainForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -91,6 +92,7 @@
|
||||
<Compile Include="tfa.Designer.cs">
|
||||
<DependentUpon>tfa.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="UserType.cs" />
|
||||
<Compile Include="util.cs" />
|
||||
<EmbeddedResource Include="auth.resx">
|
||||
<DependentUpon>auth.cs</DependentUpon>
|
||||
|
||||
20
AyaNovaQBI/UserType.cs
Normal file
20
AyaNovaQBI/UserType.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AyaNovaQBI
|
||||
{
|
||||
/// <summary>
|
||||
/// AyaNova User types
|
||||
/// </summary>
|
||||
public enum UserType : int
|
||||
{
|
||||
Service = 1,
|
||||
NotService = 2,
|
||||
Customer = 3,
|
||||
HeadOffice = 4,
|
||||
ServiceContractor = 5
|
||||
}
|
||||
}
|
||||
@@ -42,8 +42,7 @@ namespace AyaNovaQBI
|
||||
{
|
||||
if (!ValidateAndCleanServerAddress()) return;
|
||||
btnLogin.Enabled = btnTest.Enabled = false;
|
||||
// if (!util.Initialized)
|
||||
//{
|
||||
|
||||
var result = await util.InitAndConfirmAddressAsync(edServerUrl.Text);
|
||||
if (result != "OK")
|
||||
{
|
||||
@@ -51,7 +50,8 @@ namespace AyaNovaQBI
|
||||
btnLogin.Enabled = btnTest.Enabled = true;
|
||||
return;
|
||||
}
|
||||
// }
|
||||
try
|
||||
{
|
||||
var res = await util.AuthenticateAsync(edUserName.Text, edPassword.Text);
|
||||
if (!res)
|
||||
{
|
||||
@@ -60,6 +60,40 @@ namespace AyaNovaQBI
|
||||
this.DialogResult = DialogResult.Cancel;
|
||||
return;
|
||||
}
|
||||
}catch(Exception ex)
|
||||
{
|
||||
// ---------------------------
|
||||
|
||||
//---------------------------
|
||||
//Error attempting to login:
|
||||
|
||||
// POST error, code: 401, route: auth / tfa - authenticate
|
||||
|
||||
//{ "error":{ "code":"2003","message":"ErrorAPI2003"} }
|
||||
|
||||
// Unauthorized
|
||||
|
||||
// POSTED OBJECT:
|
||||
|
||||
// { "pin":"123456","tempToken":"YvIS2IovMIWUYc4NaovwhNcFXviWwEOx4qvpzt8vfQQ"}
|
||||
// ---------------------------
|
||||
// OK
|
||||
// -------------------------- -
|
||||
|
||||
|
||||
MessageBox.Show("Error attempting to login:\r\n" + ex.Message);
|
||||
this.DialogResult = DialogResult.Cancel;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
MessageBox.Show($@"TEST - LOGIN SUCCEEDED: \r\
|
||||
AyaNovaUserName: {util.AyaNovaUserName}\r\n
|
||||
JWT: {util.JWT}\r\n
|
||||
AyaNovaUserId: {util.AyaNovaUserId}\r\n
|
||||
AyaNovaUserTranslationId: {util.AyaNovaUserTranslationId}\r\n
|
||||
AyaNovaUserRoles: {util.AyaNovaUserRoles}\r\n
|
||||
AyaNovaUserType: {util.AyaNovaUserType}");
|
||||
|
||||
|
||||
btnLogin.Enabled = btnTest.Enabled = true;
|
||||
|
||||
@@ -25,6 +25,12 @@ namespace AyaNovaQBI
|
||||
internal static string GuessClientUrl { get; set; }
|
||||
|
||||
internal static string JWT { get; set; }
|
||||
internal static long AyaNovaUserId { get; set; }
|
||||
internal static long AyaNovaUserTranslationId { get; set; }
|
||||
internal static string AyaNovaUserName { get; set; }
|
||||
internal static AuthorizationRoles AyaNovaUserRoles { get; set; }
|
||||
internal static UserType AyaNovaUserType { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -92,8 +98,8 @@ namespace AyaNovaQBI
|
||||
var InnerErr = "";
|
||||
if (ex.InnerException != null)
|
||||
InnerErr = ex.InnerException.Message;
|
||||
return false;
|
||||
// throw new Exception("POST error, route: " + route + "\r\nError:" + Err + "\r\nInner error:" + InnerErr + "\r\nStack:" + ex.StackTrace + "\r\nPOSTED OBJECT:\r\n" + postJson);
|
||||
|
||||
throw new Exception("Authentication error, route: AUTH\r\nError:" + Err + "\r\nInner error:" + InnerErr);
|
||||
}
|
||||
|
||||
//ApiResponse a = await PostAsync("auth", creds.ToString());
|
||||
@@ -107,30 +113,65 @@ namespace AyaNovaQBI
|
||||
//Get temp token from response
|
||||
|
||||
var tempToken = a.ObjectResponse["data"]["tt"].Value<string>();
|
||||
string tfaPin = null;
|
||||
bool keepTrying = true;
|
||||
|
||||
//get 2fa code and send it in
|
||||
do
|
||||
{
|
||||
tfa t = new tfa();
|
||||
if (t.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) return false;
|
||||
tfaPin = t.TFAPin;
|
||||
string tfaPin = t.TFAPin;
|
||||
|
||||
dynamic tfaCreds = new JObject();
|
||||
tfaCreds.pin = tfaPin;
|
||||
tfaCreds.tempToken = tempToken;
|
||||
try
|
||||
{
|
||||
var tfaResponse = await TryPostAsync("auth/tfa-authenticate", tfaCreds.ToString(Newtonsoft.Json.Formatting.None));//trypost is no delay
|
||||
if (ProcessLoginResponse(tfaResponse)) return true;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
if (!ex.Message.Contains("2003"))//if not an authentication error (bad pin) then throw it back up for display
|
||||
throw ex;
|
||||
//otherwise eat it and let them re-enter the pin again to mirror how ayanova web client works
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} while (keepTrying);
|
||||
} while (true);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
JWT = a.ObjectResponse["data"]["token"].Value<string>();
|
||||
return true;
|
||||
return ProcessLoginResponse(a);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool ProcessLoginResponse(ApiResponse a)
|
||||
{
|
||||
if (a.ObjectResponse == null) return false;
|
||||
if (!a.HttpResponse.IsSuccessStatusCode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(a.ObjectResponse["data"]["l"].Value<bool>())//license lockout
|
||||
{
|
||||
throw new Exception("Server login from QBI is disabled due to AyaNova license issue");
|
||||
}
|
||||
|
||||
JWT = a.ObjectResponse["data"]["token"].Value<string>();
|
||||
// AyaNovaUserId= a.ObjectResponse["data"]["id"].Value<long>();//nbot here maybe in jwt
|
||||
//AyaNovaUserTranslationId = a.ObjectResponse["data"]["tid"].Value<long>();
|
||||
AyaNovaUserName = a.ObjectResponse["data"]["name"].Value<string>();
|
||||
AyaNovaUserRoles = (AuthorizationRoles)(int.Parse(a.ObjectResponse["data"]["roles"].Value<string>()));
|
||||
AyaNovaUserType = (UserType)(int.Parse(a.ObjectResponse["data"]["usertype"].Value<string>()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async static Task<ApiResponse> GetAsync(string route)
|
||||
|
||||
Reference in New Issue
Block a user