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">
|
<Compile Include="auth.Designer.cs">
|
||||||
<DependentUpon>auth.cs</DependentUpon>
|
<DependentUpon>auth.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="AuthorizationRoles.cs" />
|
||||||
<Compile Include="MainForm.cs">
|
<Compile Include="MainForm.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -91,6 +92,7 @@
|
|||||||
<Compile Include="tfa.Designer.cs">
|
<Compile Include="tfa.Designer.cs">
|
||||||
<DependentUpon>tfa.cs</DependentUpon>
|
<DependentUpon>tfa.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="UserType.cs" />
|
||||||
<Compile Include="util.cs" />
|
<Compile Include="util.cs" />
|
||||||
<EmbeddedResource Include="auth.resx">
|
<EmbeddedResource Include="auth.resx">
|
||||||
<DependentUpon>auth.cs</DependentUpon>
|
<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;
|
if (!ValidateAndCleanServerAddress()) return;
|
||||||
btnLogin.Enabled = btnTest.Enabled = false;
|
btnLogin.Enabled = btnTest.Enabled = false;
|
||||||
// if (!util.Initialized)
|
|
||||||
//{
|
|
||||||
var result = await util.InitAndConfirmAddressAsync(edServerUrl.Text);
|
var result = await util.InitAndConfirmAddressAsync(edServerUrl.Text);
|
||||||
if (result != "OK")
|
if (result != "OK")
|
||||||
{
|
{
|
||||||
@@ -51,7 +50,8 @@ namespace AyaNovaQBI
|
|||||||
btnLogin.Enabled = btnTest.Enabled = true;
|
btnLogin.Enabled = btnTest.Enabled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// }
|
try
|
||||||
|
{
|
||||||
var res = await util.AuthenticateAsync(edUserName.Text, edPassword.Text);
|
var res = await util.AuthenticateAsync(edUserName.Text, edPassword.Text);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
@@ -60,6 +60,40 @@ namespace AyaNovaQBI
|
|||||||
this.DialogResult = DialogResult.Cancel;
|
this.DialogResult = DialogResult.Cancel;
|
||||||
return;
|
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;
|
btnLogin.Enabled = btnTest.Enabled = true;
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ namespace AyaNovaQBI
|
|||||||
internal static string GuessClientUrl { get; set; }
|
internal static string GuessClientUrl { get; set; }
|
||||||
|
|
||||||
internal static string JWT { 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 = "";
|
var InnerErr = "";
|
||||||
if (ex.InnerException != null)
|
if (ex.InnerException != null)
|
||||||
InnerErr = ex.InnerException.Message;
|
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());
|
//ApiResponse a = await PostAsync("auth", creds.ToString());
|
||||||
@@ -107,30 +113,65 @@ namespace AyaNovaQBI
|
|||||||
//Get temp token from response
|
//Get temp token from response
|
||||||
|
|
||||||
var tempToken = a.ObjectResponse["data"]["tt"].Value<string>();
|
var tempToken = a.ObjectResponse["data"]["tt"].Value<string>();
|
||||||
string tfaPin = null;
|
|
||||||
bool keepTrying = true;
|
|
||||||
//get 2fa code and send it in
|
//get 2fa code and send it in
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
tfa t = new tfa();
|
tfa t = new tfa();
|
||||||
if (t.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) return false;
|
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 (true);
|
||||||
} while (keepTrying);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JWT = a.ObjectResponse["data"]["token"].Value<string>();
|
return ProcessLoginResponse(a);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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)
|
public async static Task<ApiResponse> GetAsync(string route)
|
||||||
|
|||||||
Reference in New Issue
Block a user