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

@@ -8,7 +8,7 @@ using Newtonsoft.Json.Linq;
namespace PepperDash.Core.JsonToSimpl
{
public abstract class JsonToSimplChildObjectBase: IKeyed
public abstract class JsonToSimplChildObjectBase : IKeyed
{
public event EventHandler<BoolChangeEventArgs> BoolChange;
@@ -64,9 +64,10 @@ namespace PepperDash.Core.JsonToSimpl
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;
}
}
/// <summary>
/// Set the JPath to evaluate for a given bool out index.
/// </summary>
@@ -133,20 +134,22 @@ namespace PepperDash.Core.JsonToSimpl
OnBoolChange(response.Equals("true", StringComparison.OrdinalIgnoreCase),
index, JsonToSimplConstants.BoolValueChange);
else { }
// OnBoolChange(false, index, JsonToSimplConstants.BoolValueChange);
// OnBoolChange(false, index, JsonToSimplConstants.BoolValueChange);
}
// Processes the path to a ushort, converting to ushort if able, firing off UshrtChange event
void ProcessUshortPath(ushort index)
{
string response;
if (Process(UshortPaths[index], out response)) {
if (Process(UshortPaths[index], out response))
{
ushort val;
try { val = Convert.ToUInt16(response); } catch { val = 0; }
try { val = Convert.ToUInt16(response); }
catch { val = 0; }
OnUShortChange(val, index, JsonToSimplConstants.UshortValueChange);
}
}
else { }
// OnUShortChange(0, index, JsonToSimplConstants.UshortValueChange);
// OnUShortChange(0, index, JsonToSimplConstants.UshortValueChange);
}
// Processes the path to a string property and fires of a StringChange event.
@@ -156,7 +159,7 @@ namespace PepperDash.Core.JsonToSimpl
if (Process(StringPaths[index], out response))
OnStringChange(response, index, JsonToSimplConstants.StringValueChange);
else { }
// OnStringChange("", index, JsonToSimplConstants.StringValueChange);
// OnStringChange("", index, JsonToSimplConstants.StringValueChange);
}
/// <summary>
@@ -170,7 +173,7 @@ namespace PepperDash.Core.JsonToSimpl
bool Process(string path, out string response)
{
path = GetFullPath(path);
Debug.Console(1, "JSON Child[{0}] Processing {1}", Key, path);
Debug.Console(1, "JSON Child[{0}] Processing {1}", Key, path);
response = "";
if (Master == null)
{
@@ -285,7 +288,7 @@ namespace PepperDash.Core.JsonToSimpl
protected virtual string GetFullPath(string path)
{
return (PathPrefix != null ? PathPrefix : "") +
path + (PathSuffix != null ? PathSuffix : "");
path + (PathSuffix != null ? PathSuffix : "");
}
// Helpers for events

View File

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

View File

@@ -6,92 +6,21 @@ using Crestron.SimplSharp;
namespace PepperDash.Core.PasswordManagement
{
// Example JSON password configuration object
//{
// "global":{
// "passwords":[
// {
// "key": "Password01",
// "name": "Technician Password",
// "enabled": true,
// "password": "1988"
// }
// ]
// }
//}
/// <summary>
/// Passwrod manager JSON configuration
/// JSON password configuration
/// </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>
/// Constructor
/// </summary>
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; }
/// <summary>
/// Password object configured password
/// </summary>
public string password { get; set; }
/// <summary>
/// Constructor
/// </summary>
public PasswordConfig()
{
}
}
}

View File

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

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
{
/// <summary>
/// Password Client
/// Password selected
/// </summary>
public PasswordConfig Client { get; set; }
public string Password { get; set; }
/// <summary>
/// Password selected key
/// </summary>
public ushort Key { get; set; }
/// <summary>
/// Used to build the password entered by the user
/// </summary>
@@ -35,53 +39,43 @@ namespace PepperDash.Core.PasswordManagement
/// </summary>
public PasswordClient()
{
}
PasswordManager.PasswordChange += new EventHandler<StringChangeEventArgs>(PasswordManager_PasswordChange);
}
/// <summary>
/// Initialize method
/// </summary>
/// <param name="key"></param>
public void Initialize(string key)
public void Initialize()
{
OnBoolChange(false, 0, PasswordManagementConstants.BoolEvaluatedChange);
OnBoolChange(false, 0, PasswordManagementConstants.PasswordInitializedChange);
Client = new PasswordConfig();
Password = "";
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++;
OnStringChange(password.key, i, PasswordManagementConstants.PasswordKey);
}
OnBoolChange(true, 0, PasswordManagementConstants.BoolEvaluatedChange);
OnUshrtChange((ushort)PasswordManager.Passwords.Count, 0, PasswordManagementConstants.PasswordManagerCountChange);
OnBoolChange(true, 0, PasswordManagementConstants.PasswordInitializedChange);
}
/// <summary>
/// Retrieves password by key
/// Retrieve password by index
/// </summary>
/// <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;
}
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);
Password = pw;
OnUshrtChange((ushort)Password.Length, 0, PasswordManagementConstants.PasswordLengthChange);
OnUshrtChange(key, 0, PasswordManagementConstants.PasswordSelectIndexChange);
}
/// <summary>
@@ -93,18 +87,10 @@ namespace PepperDash.Core.PasswordManagement
if (string.IsNullOrEmpty(password))
return;
if (string.Equals(Client.password, password))
{
OnBoolChange(true, 0, PasswordManagementConstants.PasswordIsValid);
}
if (string.Equals(Password, password))
OnBoolChange(true, 0, PasswordManagementConstants.PasswordValidationChange);
else
{
OnBoolChange(true, 0, PasswordManagementConstants.PasswordIsInvalid);
}
OnBoolChange(false, 0, PasswordManagementConstants.PasswordIsValid);
OnBoolChange(false, 0, PasswordManagementConstants.PasswordIsInvalid);
OnBoolChange(false, 0, PasswordManagementConstants.PasswordValidationChange);
ClearPassword();
}
@@ -117,9 +103,9 @@ namespace PepperDash.Core.PasswordManagement
public void BuildPassword(string 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);
}
@@ -129,10 +115,7 @@ namespace PepperDash.Core.PasswordManagement
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);
OnBoolChange(false, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedFeedbackChange);
}
/// <summary>
@@ -185,5 +168,21 @@ namespace PepperDash.Core.PasswordManagement
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 Crestron.SimplSharp;
using PepperDash.Core.JsonToSimpl;
using PepperDash.Core.JsonStandardObjects;
namespace PepperDash.Core.PasswordManagement
{
public class PasswordManager
{
/// <summary>
/// List of passwords configured
/// Public dictionary of known passwords
/// </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>
/// Boolean event
/// </summary>
@@ -27,96 +42,135 @@ namespace PepperDash.Core.PasswordManagement
/// String event
/// </summary>
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>
/// Constructor
/// </summary>
public PasswordManager()
{
Passwords.Clear();
}
/// <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>
/// <param name="key"></param>
/// <param name="uniqueId"></param>
public void Initialize(string uniqueId, string key)
/// <param name="password"></param>
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
{
if(string.IsNullOrEmpty(uniqueId) || string.IsNullOrEmpty(key))
{
Debug.Console(1, "PasswordManager.Initialize({0}, {1}) null or empty parameters", uniqueId, key);
return;
}
// if key exists, update the value
if(_passwords.ContainsKey(key))
_passwords[key] = password;
// else add the key & value
else
_passwords.Add(key, password);
Debug.Console(1, string.Format("PasswordManager.UpdatePassword: _password[{0}] = {1}", key, _passwords[key]));
JsonToSimplMaster master = J2SGlobal.GetMasterByFile(uniqueId);
if(master == null)
if (PasswordTimer == null)
{
Debug.Console(1, "PassowrdManager.Initialize failed:\rCould not find JSON file with uniqueID {0}", uniqueId);
return;
PasswordTimer = new CTimer((o) => PasswordTimerElapsed(), PasswordTimerElapsedMs);
Debug.Console(1, string.Format("PasswordManager.UpdatePassword: CTimer Started"));
OnBoolChange(true, 0, PasswordManagementConstants.PasswordUpdateBusyChange);
}
var passwords = master.JsonObject.ToObject<RootObject>().global.passwords;
if(passwords == null)
{
Debug.Console(1, "PasswordManager.Initialize failed:\rCould not find password object");
return;
}
foreach(var password in passwords)
else
{
if (password != null)
PasswordTimer.Reset(PasswordTimerElapsedMs);
Debug.Console(1, string.Format("PasswordManager.UpdatePassword: CTimer Reset"));
}
}
catch (Exception e)
{
var msg = string.Format("PasswordManager.UpdatePassword key-value[{0}, {1}] failed:\r{2}", key, password, e);
Debug.Console(1, msg);
}
}
/// <summary>
/// CTimer callback function
/// </summary>
private void PasswordTimerElapsed()
{
try
{
PasswordTimer.Stop();
Debug.Console(1, string.Format("PasswordManager.PasswordTimerElapsed: CTimer Stopped"));
OnBoolChange(false, 0, PasswordManagementConstants.PasswordUpdateBusyChange);
foreach (var pw in _passwords)
{
// if key exists, continue
if (Passwords.ContainsKey(pw.Key))
{
Debug.Console(1, "PasswordManager.Initialize: {0}, {1}, {2}, {3}, {4}", password.key, password.name, password.simplEnabled, password.simplType, password.password);
AddPassword(password);
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(Convert.ToUInt16(Passwords.Count), 0, PasswordManagementConstants.PasswordListCount);
OnUshrtChange((ushort)Passwords.Count, 0, PasswordManagementConstants.PasswordManagerCountChange);
}
catch(Exception e)
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);
var msg = string.Format("PasswordManager.PasswordTimerElapsed failed:\r{0}", e);
Debug.Console(1, msg);
}
}
/// <summary>
/// Adds password to the list
/// Method to change the default timer value, (default 5000ms/5s)
/// </summary>
/// <param name="password"></param>
private void AddPassword(PasswordConfig password)
/// <param name="time"></param>
public void PasswordTimerMs(ushort time)
{
if (password == null)
return;
var item = Passwords.FirstOrDefault(i => i.key.Equals(password.key));
if (item != null)
Passwords.Remove(item);
Passwords.Add(password);
PasswordTimerElapsedMs = Convert.ToInt64(time);
}
/// <summary>
/// Removes password from the list
/// Helper method for debugging to see what passwords are in the lists
/// </summary>
/// <param name="password"></param>
private void RemovePassword(PasswordConfig password)
public void ListPasswords()
{
if (password == null)
return;
var item = Passwords.FirstOrDefault(i => i.key.Equals(password.key));
if (item != null)
Passwords.Remove(item);
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>
@@ -169,5 +223,22 @@ namespace PepperDash.Core.PasswordManagement
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: AssemblyProduct("Pepperdash_Core")]
[assembly: AssemblyCopyright("Copyright © PepperDash 2019")]
[assembly: AssemblyVersion("1.0.23.*")]
[assembly: AssemblyVersion("1.0.26.*")]