mirror of
https://github.com/PepperDash/PepperDashCore.git
synced 2026-02-09 01:34:50 +00:00
Completed migration of Password Manager to PDC, added event to notify clients of a password update
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -108,6 +108,7 @@ namespace PepperDash.Core.JsonToSimpl
|
||||
{
|
||||
Debug.SetDebugLevel(level);
|
||||
}
|
||||
|
||||
public override void Save()
|
||||
{
|
||||
// this code is duplicated in the other masters!!!!!!!!!!!!!
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
//}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.*")]
|
||||
|
||||
Reference in New Issue
Block a user