Completed migration of Password Manager to PDC, added event to notify clients of a password update

This commit is contained in:
Jason DeVito
2019-10-21 07:42:56 -05:00
parent 55c2e6f32f
commit 7e82a4f853
10 changed files with 807 additions and 223 deletions

View File

@@ -64,7 +64,8 @@ namespace PepperDash.Core.JsonToSimpl
Debug.Console(1, "JSON Child [{0}] cannot link to master {1}", key, masterUniqueId); Debug.Console(1, "JSON Child [{0}] cannot link to master {1}", key, masterUniqueId);
} }
public void SetPathPrefix(string pathPrefix) { public void SetPathPrefix(string pathPrefix)
{
PathPrefix = pathPrefix; PathPrefix = pathPrefix;
} }
/// <summary> /// <summary>
@@ -140,9 +141,11 @@ namespace PepperDash.Core.JsonToSimpl
void ProcessUshortPath(ushort index) void ProcessUshortPath(ushort index)
{ {
string response; string response;
if (Process(UshortPaths[index], out response)) { if (Process(UshortPaths[index], out response))
{
ushort val; ushort val;
try { val = Convert.ToUInt16(response); } catch { val = 0; } try { val = Convert.ToUInt16(response); }
catch { val = 0; }
OnUShortChange(val, index, JsonToSimplConstants.UshortValueChange); OnUShortChange(val, index, JsonToSimplConstants.UshortValueChange);
} }
else { } else { }

View File

@@ -108,6 +108,7 @@ namespace PepperDash.Core.JsonToSimpl
{ {
Debug.SetDebugLevel(level); Debug.SetDebugLevel(level);
} }
public override void Save() public override void Save()
{ {
// this code is duplicated in the other masters!!!!!!!!!!!!! // this code is duplicated in the other masters!!!!!!!!!!!!!

View File

@@ -6,92 +6,21 @@ using Crestron.SimplSharp;
namespace PepperDash.Core.PasswordManagement namespace PepperDash.Core.PasswordManagement
{ {
// Example JSON password configuration object
//{
// "global":{
// "passwords":[
// {
// "key": "Password01",
// "name": "Technician Password",
// "enabled": true,
// "password": "1988"
// }
// ]
// }
//}
/// <summary> /// <summary>
/// Passwrod manager JSON configuration /// JSON password configuration
/// </summary> /// </summary>
public class PasswordConfig public class PasswordConfig
{ {
/// <summary>
/// Key used to search for object in JSON array
/// </summary>
public string key { get; set; }
/// <summary>
/// Friendly name of password object
/// </summary>
public string name { get; set; }
/// <summary>
/// Password object enabled
/// </summary>
public bool enabled { get; set; }
/// <summary>
///
/// </summary>
public ushort simplEnabled
{
get { return (ushort)(enabled ? 1 : 0); }
set { enabled = Convert.ToBoolean(value); }
}
/// <summary> /// <summary>
/// Password object configured password /// Password object configured password
/// </summary> /// </summary>
public string password { get; set; } public string password { get; set; }
/// <summary> /// <summary>
/// Password type
/// </summary>
private int type { get; set; }
/// <summary>
/// Password Type for S+
/// </summary>
public ushort simplType
{
get { return Convert.ToUInt16(type); }
set { type = value; }
}
/// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public PasswordConfig() public PasswordConfig()
{
simplEnabled = 0;
simplType = 0;
}
}
/// <summary>
/// Global JSON object
/// </summary>
public class GlobalConfig
{
public List<PasswordConfig> passwords { get; set; }
/// <summary>
/// Constructor
/// </summary>
public GlobalConfig()
{ {
} }
} }
/// <summary>
/// Root JSON object
/// </summary>
public class RootObject
{
public GlobalConfig global { get; set; }
}
} }

View File

@@ -18,19 +18,19 @@ namespace PepperDash.Core.PasswordManagement
/// <summary> /// <summary>
/// Evaluated boolean change constant /// Evaluated boolean change constant
/// </summary> /// </summary>
public const ushort BoolEvaluatedChange = 2; public const ushort PasswordInitializedChange = 2;
/// <summary>
/// Update busy change const
/// </summary>
public const ushort PasswordUpdateBusyChange = 3;
/// <summary> /// <summary>
/// Password is valid change constant /// Password is valid change constant
/// </summary> /// </summary>
public const ushort PasswordIsValid = 3; public const ushort PasswordValidationChange = 4;
/// <summary>
/// Password is invalid change constant
/// </summary>
public const ushort PasswordIsInvalid = 4;
/// <summary> /// <summary>
/// Password LED change constant /// Password LED change constant
/// </summary> /// </summary>
public const ushort PasswordLedChange = 5; public const ushort PasswordLedFeedbackChange = 5;
/// <summary> /// <summary>
/// Generic ushort value change constant /// Generic ushort value change constant
@@ -39,27 +39,19 @@ namespace PepperDash.Core.PasswordManagement
/// <summary> /// <summary>
/// Password count /// Password count
/// </summary> /// </summary>
public const ushort PasswordListCount = 102; public const ushort PasswordManagerCountChange = 102;
/// <summary>
/// Password selecte index change constant
/// </summary>
public const ushort PasswordSelectIndexChange = 103;
/// <summary> /// <summary>
/// Password length /// Password length
/// </summary> /// </summary>
public const ushort SelectedPasswordLength = 103; public const ushort PasswordLengthChange = 104;
/// <summary>
/// Password to validate length
/// </summary>
public const ushort UserEnteredPasswordLength = 104;
/// <summary> /// <summary>
/// Generic string value change constant /// Generic string value change constant
/// </summary> /// </summary>
public const ushort StringValueChange = 201; public const ushort StringValueChange = 201;
/// <summary>
/// Password key change constant
/// </summary>
public const ushort PasswordKey = 202;
/// <summary>
/// Password selected key change constant
/// </summary>
public const ushort PasswordKeySelected = 203;
} }
} }

View File

@@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Core.PasswordManagement
{
// Example JSON password array configuration object
//{
// "global":{
// "passwords":[
// {
// "key": "Password01",
// "name": "Technician Password",
// "enabled": true,
// "password": "1988"
// }
// ]
// }
//}
/// <summary>
/// JSON password array configuration object
/// </summary>
//public class PasswordConfig
//{
// /// <summary>
// /// Key used to search for object in JSON array
// /// </summary>
// public string key { get; set; }
// /// <summary>
// /// Friendly name of password object
// /// </summary>
// public string name { get; set; }
// /// <summary>
// /// Password object enabled
// /// </summary>
// public bool enabled { get; set; }
// /// <summary>
// ///
// /// </summary>
// public ushort simplEnabled
// {
// get { return (ushort)(enabled ? 1 : 0); }
// set { enabled = Convert.ToBoolean(value); }
// }
// /// <summary>
// /// Password object configured password
// /// </summary>
// public string password { get; set; }
// /// <summary>
// /// Password type
// /// </summary>
// private int type { get; set; }
// /// <summary>
// /// Password Type for S+
// /// </summary>
// public ushort simplType
// {
// get { return Convert.ToUInt16(type); }
// set { type = value; }
// }
// /// <summary>
// /// Password path
// /// **FUTURE** implementation of saving passwords recieved from Fusion or other external sources back to config
// /// </summary>
// public string path { get; set; }
// /// <summary>
// /// Constructor
// /// </summary>
// public PasswordConfig()
// {
// simplEnabled = 0;
// simplType = 0;
// }
//}
// Example JSON password collections configuration object
//{
// "global": {
// "passwords": {
// "1": {
// "name": "Technician Password",
// "password": "2468"
// },
// "2": {
// "name": "System Password",
// "password": "123456"
// },
// "3": {
// "name": "Master Password",
// "password": "abc123"
// },
// "5": {
// "name": "Backdoor Password",
// "password": "1988"
// },
// "10": {
// "name": "Backdoor Password",
// "password": "1988"
// }
// }
// }
//}
/// <summary>
/// JSON password array configuration object
/// </summary>
public class PasswordConfig
{
/// <summary>
/// Password object configured password
/// </summary>
public string password { get; set; }
/// <summary>
/// Constructor
/// </summary>
public PasswordConfig()
{
}
}
/// <summary>
/// Global JSON object
/// </summary>
//public class GlobalConfig
//{
// //public List<PasswordConfig> passwords { get; set; }
// public Dictionary<uint, PasswordConfig> passwords { get; set; }
// /// <summary>
// /// Constructor
// /// </summary>
// public GlobalConfig()
// {
// }
//}
/// <summary>
/// Root JSON object
/// </summary>
//public class RootObject
//{
// public GlobalConfig global { get; set; }
//}
}

View File

@@ -0,0 +1,207 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Core.PasswordManagement
{
public class PasswordClient
{
/// <summary>
/// Password Client
/// </summary>
public PasswordConfig Client { get; set; }
/// <summary>
/// Used to build the password entered by the user
/// </summary>
public string PasswordToValidate { get; set; }
/// <summary>
/// Boolean event
/// </summary>
public event EventHandler<BoolChangeEventArgs> BoolChange;
/// <summary>
/// Ushort event
/// </summary>
public event EventHandler<UshrtChangeEventArgs> UshrtChange;
/// <summary>
/// String event
/// </summary>
public event EventHandler<StringChangeEventArgs> StringChange;
/// <summary>
/// Constructor
/// </summary>
public PasswordClient()
{
}
/// <summary>
/// Initialize method
/// </summary>
/// <param name="key"></param>
public void Initialize(string key)
{
OnBoolChange(false, 0, PasswordManagementConstants.BoolEvaluatedChange);
Client = new PasswordConfig();
PasswordToValidate = "";
// there has to be a better way to get the index of the current index of password
ushort i = 0;
foreach (var password in PasswordManager.Passwords)
{
i++;
OnUshrtChange((ushort)password.Key, (ushort)password.Key, PasswordManagementConstants.PasswordKey);
}
OnBoolChange(true, 0, PasswordManagementConstants.BoolEvaluatedChange);
}
/// <summary>
/// Retrieves password by key
/// </summary>
/// <param name="key"></param>
//public void GetPasswordByKey(string key)
//{
// if (string.IsNullOrEmpty(key))
// {
// Debug.Console(1, "PassowrdClient.GetPasswordByKey failed:\rKey {0} is null or empty", key);
// return;
// }
// PasswordConfig password = PasswordManager.Passwords.FirstOrDefault(p => p.key.Equals(key));
// if (password == null)
// {
// OnUshrtChange(0, 0, PasswordManagementConstants.SelectedPasswordLength);
// return;
// }
// Client = password;
// OnUshrtChange((ushort)Client.password.Length, 0, PasswordManagementConstants.SelectedPasswordLength);
// OnStringChange(Client.key, 0, PasswordManagementConstants.PasswordKeySelected);
//}
/// <summary>
/// Retrieve password by index
/// </summary>
/// <param name="index"></param>
public void GetPasswordByIndex(ushort key)
{
PasswordConfig pw = PasswordManager.Passwords[key];
if (pw == null)
{
OnUshrtChange(0, 0, PasswordManagementConstants.SelectedPasswordLength);
return;
}
Client = pw;
OnUshrtChange((ushort)Client.password.Length, 0, PasswordManagementConstants.SelectedPasswordLength);
OnUshrtChange(key, 0, PasswordManagementConstants.PasswordKeySelected);
}
/// <summary>
/// Password validation method
/// </summary>
/// <param name="password"></param>
public void ValidatePassword(string password)
{
if (string.IsNullOrEmpty(password))
return;
if (string.Equals(Client.password, password))
{
OnBoolChange(true, 0, PasswordManagementConstants.PasswordIsValid);
}
else
{
OnBoolChange(true, 0, PasswordManagementConstants.PasswordIsInvalid);
}
OnBoolChange(false, 0, PasswordManagementConstants.PasswordIsValid);
OnBoolChange(false, 0, PasswordManagementConstants.PasswordIsInvalid);
ClearPassword();
}
/// <summary>
/// Builds the user entered passwrod string, will attempt to validate the user entered
/// password against the selected password when the length of the 2 are equal
/// </summary>
/// <param name="data"></param>
public void BuildPassword(string data)
{
PasswordToValidate = String.Concat(PasswordToValidate, data);
OnBoolChange(true, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedChange);
if (PasswordToValidate.Length == Client.password.Length)
ValidatePassword(PasswordToValidate);
}
/// <summary>
/// Clears the user entered password and resets the LEDs
/// </summary>
public void ClearPassword()
{
PasswordToValidate = "";
OnBoolChange(true, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedChange);
for(var i = 1; i <= Client.password.Length; i++)
OnBoolChange(false, (ushort)i, PasswordManagementConstants.PasswordLedChange);
}
/// <summary>
/// Protected boolean change event handler
/// </summary>
/// <param name="state"></param>
/// <param name="index"></param>
/// <param name="type"></param>
protected void OnBoolChange(bool state, ushort index, ushort type)
{
var handler = BoolChange;
if (handler != null)
{
var args = new BoolChangeEventArgs(state, type);
args.Index = index;
BoolChange(this, args);
}
}
/// <summary>
/// Protected ushort change event handler
/// </summary>
/// <param name="value"></param>
/// <param name="index"></param>
/// <param name="type"></param>
protected void OnUshrtChange(ushort value, ushort index, ushort type)
{
var handler = UshrtChange;
if (handler != null)
{
var args = new UshrtChangeEventArgs(value, type);
args.Index = index;
UshrtChange(this, args);
}
}
/// <summary>
/// Protected string change event handler
/// </summary>
/// <param name="value"></param>
/// <param name="index"></param>
/// <param name="type"></param>
protected void OnStringChange(string value, ushort index, ushort type)
{
var handler = StringChange;
if (handler != null)
{
var args = new StringChangeEventArgs(value, type);
args.Index = index;
StringChange(this, args);
}
}
}
}

View File

@@ -0,0 +1,233 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Crestron.SimplSharp;
using PepperDash.Core.JsonToSimpl;
using PepperDash.Core.JsonStandardObjects;
namespace PepperDash.Core.PasswordManagement
{
public class PasswordManager
{
/// <summary>
/// List of passwords configured
/// </summary>
public static Dictionary<uint, PasswordConfig> Passwords = new Dictionary<uint, PasswordConfig>();
private Dictionary<uint, PasswordConfig> TempPasswords = new Dictionary<uint, PasswordConfig>();
CTimer UpdateTimer;
public long UpdateTimerElapsedMs = 5000;
/// <summary>
/// Boolean event
/// </summary>
public event EventHandler<BoolChangeEventArgs> BoolChange;
/// <summary>
/// Ushort event
/// </summary>
public event EventHandler<UshrtChangeEventArgs> UshrtChange;
/// <summary>
/// String event
/// </summary>
public event EventHandler<StringChangeEventArgs> StringChange;
/// <summary>
/// Constructor
/// </summary>
public PasswordManager()
{
Passwords.Clear();
}
/// <summary>
/// Initialize method
/// </summary>
/// <param name="key"></param>
/// <param name="uniqueId"></param>
//public void Initialize(string uniqueId, string key)
//{
// OnBoolChange(false, 0, PasswordManagementConstants.BoolEvaluatedChange);
// try
// {
// if(string.IsNullOrEmpty(uniqueId) || string.IsNullOrEmpty(key))
// {
// Debug.Console(1, "PasswordManager.Initialize({0}, {1}) null or empty parameters", uniqueId, key);
// return;
// }
// JsonToSimplMaster master = J2SGlobal.GetMasterByFile(uniqueId);
// if(master == null)
// {
// Debug.Console(1, "PassowrdManager.Initialize failed:\rCould not find JSON file with uniqueID {0}", uniqueId);
// return;
// }
// var global = master.JsonObject.ToObject<RootObject>().global;
// var passwords = global.passwords;
// if(passwords == null)
// {
// Debug.Console(1, "PasswordManager.Initialize failed:\rCould not find password object");
// return;
// }
// foreach(var password in passwords)
// {
// if (password != null)
// {
// var index = passwords.IndexOf(password);
// password.path = string.Format("global.passwords[{0}]", index);
// Debug.Console(1, "PasswordManager.Initialize: {0}, {1}, {2}, {3}, {4}, {5}", password.key, password.name, password.simplEnabled, password.simplType, password.password, password.path);
// //AddPassword(password);
// OnStringChange(password.path, (ushort)index, PasswordManagementConstants.FullPathToPassword);
// OnStringChange(password.key, (ushort)index, PasswordManagementConstants.PasswordKey);
// }
// }
// OnUshrtChange(Convert.ToUInt16(Passwords.Count), 0, PasswordManagementConstants.PasswordListCount);
// }
// catch(Exception e)
// {
// var msg = string.Format("PasswordManager.Initialize({0}, {1}) failed:\r{2}", uniqueId, key, e.Message);
// CrestronConsole.PrintLine(msg);
// ErrorLog.Error(msg);
// }
// finally
// {
// OnBoolChange(true, 0, PasswordManagementConstants.BoolEvaluatedChange);
// }
//}
/// <summary>
/// Adds password to the list
/// </summary>
/// <param name="password"></param>
//private void AddPassword(PasswordConfig password)
//{
// if (password == null)
// return;
// var item = Passwords.FirstOrDefault(i => i.key.Equals(password.key));
// if (item != null)
// Passwords.Remove(item);
// Passwords.Add(password);
// Passwords.Sort((x, y) => string.Compare(x.key, y.key));
//}
/// <summary>
/// Removes password from the list
/// </summary>
/// <param name="password"></param>
//private void RemovePassword(PasswordConfig password)
//{
// if (password == null)
// return;
// var item = Passwords.FirstOrDefault(i => i.key.Equals(password.key));
// if (item != null)
// Passwords.Remove(item);
//}
/// <summary>
/// Updates password stored in the dictonary
/// </summary>
/// <param name="uniqueId"></param>
/// <param name="key"></param>
/// <param name="password"></param>
public void UpdatePassword(ushort key, string password)
{
if (string.IsNullOrEmpty(password))
return;
var pw = TempPasswords[key];
if (pw == null)
{
pw = new PasswordConfig();
}
pw.password = password;
if (UpdateTimer == null)
{
// (o) => SavePasswords removes the need to create a callback method that takes in an object
UpdateTimer = new CTimer((o) => StorePassword(), UpdateTimerElapsedMs);
}
else
{
UpdateTimer.Reset();
}
}
/// <summary>
/// Stores the updated passwords in TempPassword in the Passwords dictionary
/// </summary>
private void StorePassword()
{
UpdateTimer.Stop();
foreach (var tempPw in TempPasswords)
{
Passwords[tempPw.Key] = tempPw.Value;
}
TempPasswords.Clear();
}
/// <summary>
/// Protected boolean change event handler
/// </summary>
/// <param name="state"></param>
/// <param name="index"></param>
/// <param name="type"></param>
protected void OnBoolChange(bool state, ushort index, ushort type)
{
var handler = BoolChange;
if (handler != null)
{
var args = new BoolChangeEventArgs(state, type);
args.Index = index;
BoolChange(this, args);
}
}
/// <summary>
/// Protected ushort change event handler
/// </summary>
/// <param name="state"></param>
/// <param name="index"></param>
/// <param name="type"></param>
protected void OnUshrtChange(ushort value, ushort index, ushort type)
{
var handler = UshrtChange;
if (handler != null)
{
var args = new UshrtChangeEventArgs(value, type);
args.Index = index;
UshrtChange(this, args);
}
}
/// <summary>
/// Protected string change event handler
/// </summary>
/// <param name="value"></param>
/// <param name="index"></param>
/// <param name="type"></param>
protected void OnStringChange(string value, ushort index, ushort type)
{
var handler = StringChange;
if (handler != null)
{
var args = new StringChangeEventArgs(value, type);
args.Index = index;
StringChange(this, args);
}
}
}
}

View File

@@ -9,9 +9,13 @@ namespace PepperDash.Core.PasswordManagement
public class PasswordClient public class PasswordClient
{ {
/// <summary> /// <summary>
/// Password Client /// Password selected
/// </summary> /// </summary>
public PasswordConfig Client { get; set; } public string Password { get; set; }
/// <summary>
/// Password selected key
/// </summary>
public ushort Key { get; set; }
/// <summary> /// <summary>
/// Used to build the password entered by the user /// Used to build the password entered by the user
/// </summary> /// </summary>
@@ -35,53 +39,43 @@ namespace PepperDash.Core.PasswordManagement
/// </summary> /// </summary>
public PasswordClient() public PasswordClient()
{ {
PasswordManager.PasswordChange += new EventHandler<StringChangeEventArgs>(PasswordManager_PasswordChange);
} }
/// <summary> /// <summary>
/// Initialize method /// Initialize method
/// </summary> /// </summary>
/// <param name="key"></param> public void Initialize()
public void Initialize(string key)
{ {
OnBoolChange(false, 0, PasswordManagementConstants.BoolEvaluatedChange); OnBoolChange(false, 0, PasswordManagementConstants.PasswordInitializedChange);
Client = new PasswordConfig(); Password = "";
PasswordToValidate = ""; PasswordToValidate = "";
// there has to be a better way to get the index of the current index of password OnUshrtChange((ushort)PasswordManager.Passwords.Count, 0, PasswordManagementConstants.PasswordManagerCountChange);
ushort i = 0; OnBoolChange(true, 0, PasswordManagementConstants.PasswordInitializedChange);
foreach (var password in PasswordManager.Passwords)
{
i++;
OnStringChange(password.key, i, PasswordManagementConstants.PasswordKey);
}
OnBoolChange(true, 0, PasswordManagementConstants.BoolEvaluatedChange);
} }
/// <summary> /// <summary>
/// Retrieves password by key /// Retrieve password by index
/// </summary> /// </summary>
/// <param name="key"></param> /// <param name="key"></param>
public void GetPasswordByKey(string key) public void GetPasswordByIndex(ushort key)
{ {
if (string.IsNullOrEmpty(key)) OnUshrtChange((ushort)PasswordManager.Passwords.Count, 0, PasswordManagementConstants.PasswordManagerCountChange);
Key = key;
var pw = PasswordManager.Passwords[Key];
if (pw == null)
{ {
Debug.Console(1, "PassowrdClient.GetPasswordByKey failed:\rKey {0} is null or empty", key); OnUshrtChange(0, 0, PasswordManagementConstants.PasswordLengthChange);
return; return;
} }
PasswordConfig password = PasswordManager.Passwords.FirstOrDefault(p => p.key.Equals(key)); Password = pw;
if (password == null) OnUshrtChange((ushort)Password.Length, 0, PasswordManagementConstants.PasswordLengthChange);
{ OnUshrtChange(key, 0, PasswordManagementConstants.PasswordSelectIndexChange);
OnUshrtChange(0, 0, PasswordManagementConstants.SelectedPasswordLength);
return;
}
Client = password;
OnUshrtChange((ushort)Client.password.Length, 0, PasswordManagementConstants.SelectedPasswordLength);
OnStringChange(Client.key, 0, PasswordManagementConstants.PasswordKeySelected);
} }
/// <summary> /// <summary>
@@ -93,18 +87,10 @@ namespace PepperDash.Core.PasswordManagement
if (string.IsNullOrEmpty(password)) if (string.IsNullOrEmpty(password))
return; return;
if (string.Equals(Client.password, password)) if (string.Equals(Password, password))
{ OnBoolChange(true, 0, PasswordManagementConstants.PasswordValidationChange);
OnBoolChange(true, 0, PasswordManagementConstants.PasswordIsValid);
}
else else
{ OnBoolChange(false, 0, PasswordManagementConstants.PasswordValidationChange);
OnBoolChange(true, 0, PasswordManagementConstants.PasswordIsInvalid);
}
OnBoolChange(false, 0, PasswordManagementConstants.PasswordIsValid);
OnBoolChange(false, 0, PasswordManagementConstants.PasswordIsInvalid);
ClearPassword(); ClearPassword();
} }
@@ -117,9 +103,9 @@ namespace PepperDash.Core.PasswordManagement
public void BuildPassword(string data) public void BuildPassword(string data)
{ {
PasswordToValidate = String.Concat(PasswordToValidate, data); PasswordToValidate = String.Concat(PasswordToValidate, data);
OnBoolChange(true, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedChange); OnBoolChange(true, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedFeedbackChange);
if (PasswordToValidate.Length == Client.password.Length) if (PasswordToValidate.Length == Password.Length)
ValidatePassword(PasswordToValidate); ValidatePassword(PasswordToValidate);
} }
@@ -129,10 +115,7 @@ namespace PepperDash.Core.PasswordManagement
public void ClearPassword() public void ClearPassword()
{ {
PasswordToValidate = ""; PasswordToValidate = "";
OnBoolChange(true, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedChange); OnBoolChange(false, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedFeedbackChange);
for(var i = 1; i <= Client.password.Length; i++)
OnBoolChange(false, (ushort)i, PasswordManagementConstants.PasswordLedChange);
} }
/// <summary> /// <summary>
@@ -185,5 +168,21 @@ namespace PepperDash.Core.PasswordManagement
StringChange(this, args); StringChange(this, args);
} }
} }
/// <summary>
/// If password changes while selected change event will be notifed and update the client
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
protected void PasswordManager_PasswordChange(object sender, StringChangeEventArgs args)
{
//throw new NotImplementedException();
if (Key == args.Index)
{
//PasswordSelectedKey = args.Index;
//PasswordSelected = args.StringValue;
GetPasswordByIndex(args.Index);
}
}
} }
} }

View File

@@ -6,15 +6,30 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using PepperDash.Core.JsonToSimpl; using PepperDash.Core.JsonToSimpl;
using PepperDash.Core.JsonStandardObjects;
namespace PepperDash.Core.PasswordManagement namespace PepperDash.Core.PasswordManagement
{ {
public class PasswordManager public class PasswordManager
{ {
/// <summary> /// <summary>
/// List of passwords configured /// Public dictionary of known passwords
/// </summary> /// </summary>
public static List<PasswordConfig> Passwords = new List<PasswordConfig>(); public static Dictionary<uint, string> Passwords = new Dictionary<uint, string>();
/// <summary>
/// Private dictionary, used when passwords are updated
/// </summary>
private Dictionary<uint, string> _passwords = new Dictionary<uint, string>();
/// <summary>
/// Timer used to wait until password changes have stopped before updating the dictionary
/// </summary>
CTimer PasswordTimer;
/// <summary>
/// Timer length
/// </summary>
public long PasswordTimerElapsedMs = 5000;
/// <summary> /// <summary>
/// Boolean event /// Boolean event
/// </summary> /// </summary>
@@ -27,96 +42,135 @@ namespace PepperDash.Core.PasswordManagement
/// String event /// String event
/// </summary> /// </summary>
public event EventHandler<StringChangeEventArgs> StringChange; public event EventHandler<StringChangeEventArgs> StringChange;
/// <summary>
/// Event to notify clients of an updated password at the specified index (uint)
/// </summary>
public static event EventHandler<StringChangeEventArgs> PasswordChange;
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public PasswordManager() public PasswordManager()
{ {
Passwords.Clear();
} }
/// <summary> /// <summary>
/// Initialize method /// Initialize password manager
/// </summary>
public void Initialize()
{
if (Passwords == null)
Passwords = new Dictionary<uint, string>();
if (_passwords == null)
_passwords = new Dictionary<uint, string>();
OnBoolChange(true, 0, PasswordManagementConstants.PasswordInitializedChange);
}
/// <summary>
/// Updates password stored in the dictonary
/// </summary> /// </summary>
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="uniqueId"></param> /// <param name="password"></param>
public void Initialize(string uniqueId, string key) public void UpdatePassword(ushort key, string password)
{ {
OnBoolChange(false, 0, PasswordManagementConstants.BoolEvaluatedChange); // validate the parameters
if (key > 0 && string.IsNullOrEmpty(password))
{
Debug.Console(1, string.Format("PasswordManager.UpdatePassword: key [{0}] or password are not valid", key, password));
return;
}
try try
{ {
if(string.IsNullOrEmpty(uniqueId) || string.IsNullOrEmpty(key)) // if key exists, update the value
{ if(_passwords.ContainsKey(key))
Debug.Console(1, "PasswordManager.Initialize({0}, {1}) null or empty parameters", uniqueId, key); _passwords[key] = password;
return; // else add the key & value
} else
_passwords.Add(key, password);
JsonToSimplMaster master = J2SGlobal.GetMasterByFile(uniqueId); Debug.Console(1, string.Format("PasswordManager.UpdatePassword: _password[{0}] = {1}", key, _passwords[key]));
if(master == null)
{
Debug.Console(1, "PassowrdManager.Initialize failed:\rCould not find JSON file with uniqueID {0}", uniqueId);
return;
}
var passwords = master.JsonObject.ToObject<RootObject>().global.passwords; if (PasswordTimer == null)
if(passwords == null)
{ {
Debug.Console(1, "PasswordManager.Initialize failed:\rCould not find password object"); PasswordTimer = new CTimer((o) => PasswordTimerElapsed(), PasswordTimerElapsedMs);
return; Debug.Console(1, string.Format("PasswordManager.UpdatePassword: CTimer Started"));
OnBoolChange(true, 0, PasswordManagementConstants.PasswordUpdateBusyChange);
} }
else
foreach(var password in passwords)
{ {
if (password != null) PasswordTimer.Reset(PasswordTimerElapsedMs);
{ Debug.Console(1, string.Format("PasswordManager.UpdatePassword: CTimer Reset"));
Debug.Console(1, "PasswordManager.Initialize: {0}, {1}, {2}, {3}, {4}", password.key, password.name, password.simplEnabled, password.simplType, password.password);
AddPassword(password);
} }
} }
OnUshrtChange(Convert.ToUInt16(Passwords.Count), 0, PasswordManagementConstants.PasswordListCount);
}
catch (Exception e) catch (Exception e)
{ {
var msg = string.Format("PasswordManager.Initialize({0}, {1}) failed:\r{2}", uniqueId, key, e.Message); var msg = string.Format("PasswordManager.UpdatePassword key-value[{0}, {1}] failed:\r{2}", key, password, e);
CrestronConsole.PrintLine(msg); Debug.Console(1, msg);
ErrorLog.Error(msg);
}
finally
{
OnBoolChange(true, 0, PasswordManagementConstants.BoolEvaluatedChange);
} }
} }
/// <summary> /// <summary>
/// Adds password to the list /// CTimer callback function
/// </summary> /// </summary>
/// <param name="password"></param> private void PasswordTimerElapsed()
private void AddPassword(PasswordConfig password)
{ {
if (password == null) try
return; {
PasswordTimer.Stop();
var item = Passwords.FirstOrDefault(i => i.key.Equals(password.key)); Debug.Console(1, string.Format("PasswordManager.PasswordTimerElapsed: CTimer Stopped"));
if (item != null) OnBoolChange(false, 0, PasswordManagementConstants.PasswordUpdateBusyChange);
Passwords.Remove(item); foreach (var pw in _passwords)
Passwords.Add(password); {
// if key exists, continue
if (Passwords.ContainsKey(pw.Key))
{
Debug.Console(1, string.Format("PasswordManager.PasswordTimerElapsed: pw.key[{0}] = {1}", pw.Key, pw.Value));
if (Passwords[pw.Key] != _passwords[pw.Key])
{
Passwords[pw.Key] = _passwords[pw.Key];
Debug.Console(1, string.Format("PasswordManager.PasswordTimerElapsed: Updated Password[{0} = {1}", pw.Key, Passwords[pw.Key]));
OnPasswordChange(Passwords[pw.Key], (ushort)pw.Key, PasswordManagementConstants.StringValueChange);
}
}
// else add the key & value
else
{
Passwords.Add(pw.Key, pw.Value);
}
}
OnUshrtChange((ushort)Passwords.Count, 0, PasswordManagementConstants.PasswordManagerCountChange);
}
catch (Exception e)
{
var msg = string.Format("PasswordManager.PasswordTimerElapsed failed:\r{0}", e);
Debug.Console(1, msg);
}
} }
/// <summary> /// <summary>
/// Removes password from the list /// Method to change the default timer value, (default 5000ms/5s)
/// </summary> /// </summary>
/// <param name="password"></param> /// <param name="time"></param>
private void RemovePassword(PasswordConfig password) public void PasswordTimerMs(ushort time)
{ {
if (password == null) PasswordTimerElapsedMs = Convert.ToInt64(time);
return; }
var item = Passwords.FirstOrDefault(i => i.key.Equals(password.key)); /// <summary>
if (item != null) /// Helper method for debugging to see what passwords are in the lists
Passwords.Remove(item); /// </summary>
public void ListPasswords()
{
Debug.Console(0, "PasswordManager.ListPasswords:\r");
foreach (var pw in Passwords)
Debug.Console(0, "Passwords[{0}]: {1}\r", pw.Key, pw.Value);
Debug.Console(0, "\n");
foreach (var pw in _passwords)
Debug.Console(0, "_passwords[{0}]: {1}\r", pw.Key, pw.Value);
} }
/// <summary> /// <summary>
@@ -169,5 +223,22 @@ namespace PepperDash.Core.PasswordManagement
StringChange(this, args); StringChange(this, args);
} }
} }
/// <summary>
/// Protected password change event handler
/// </summary>
/// <param name="value"></param>
/// <param name="index"></param>
/// <param name="type"></param>
protected void OnPasswordChange(string value, ushort index, ushort type)
{
var handler = PasswordChange;
if (handler != null)
{
var args = new StringChangeEventArgs(value, type);
args.Index = index;
PasswordChange(this, args);
}
}
} }
} }

View File

@@ -4,4 +4,4 @@
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Pepperdash_Core")] [assembly: AssemblyProduct("Pepperdash_Core")]
[assembly: AssemblyCopyright("Copyright © PepperDash 2019")] [assembly: AssemblyCopyright("Copyright © PepperDash 2019")]
[assembly: AssemblyVersion("1.0.23.*")] [assembly: AssemblyVersion("1.0.26.*")]