using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Imaging; using Comal.Classes; using InABox.Clients; using InABox.Core; using InABox.DynamicGrid; using InABox.Mail; using InABox.WPF; using NPOI.SS.Formula.Functions; using PRS.Shared; using PRSDesktop.Panels.Users; using Syncfusion.Windows.Shared; namespace PRSDesktop { internal class UserGrid : DynamicDataGrid { private bool ShowAll; public UserGrid() { AddButton("Show All", PRSDesktop.Resources.anonymous.AsBitmapImage(Color.White), ToggleDisabledUsers); ActionColumns.Add(new DynamicTickColumn(x => x.Logins, null, PRSDesktop.Resources.tick.AsBitmapImage(), null, null)); HiddenColumns.Add(x => x.AuthenticatorToken); HiddenColumns.Add(x => x.Logins); HiddenColumns.Add(x => x.Password); OnAfterSave += AfterSave; OnCustomiseEditor += UserGrid_OnCustomiseEditor; OnEditorValueChanged += UserGrid_OnEditorValueChanged; if (Security.IsAllowed()) ActionColumns.Add(new DynamicImageColumn(EmailImage, SendEmail)); } protected override void DoReconfigure(FluentList options) { base.DoReconfigure(options); options.AddRange(DynamicGridOption.RecordCount, DynamicGridOption.FilterRows, DynamicGridOption.MultiSelect, DynamicGridOption.SelectColumns); } private bool SendEmail(CoreRow? row) { if (row is null) return false; User user = row.ToObject(); var menu = new ContextMenu(); menu.AddItem("PRS Site App", null, () => { CreateLink(user, @"prssite://open/", @"http://www.prssite.com/open/", CreateURLs(new string[] { "remote.com-al.com.au:8050" })); }); menu.AddItem("PRS Timebench", null, () => { CreateLink(user, @"prsmobile://open/", @"http://www.prsmobile.com/open/", CreateURLs(App.DatabaseSettings.URLs)); }); menu.IsOpen = true; return true; } private void CreateLink(User user, string ioslink, string androidlink, string URLs) { if (string.IsNullOrWhiteSpace(ioslink)) return; var edt = new NumberEdit("Enter link expiry time in minutes", 10, 300, 10); bool result = (bool)edt.ShowDialog(); if (!result) return; var expiry = edt.Value; string toEncrypt = URLs + "," + user.UserID + "," + user.Password + "," + DateTime.Now.AddMinutes(expiry); string encrypted = Encryption.Encrypt(toEncrypt, "logindetailslink", true); ioslink = ioslink + encrypted; androidlink = androidlink + encrypted; string emailcontent = "Please ensure PRS Mobile is closed, then choose a link below:" + Environment.NewLine + Environment.NewLine + "For Apple devices, click this link: " + ioslink + Environment.NewLine + Environment.NewLine + "For Android devices (Samsung, Google, Xiaomi, Oppo, Vivo, Huawei, Motorola etc), click this link: " + androidlink + Environment.NewLine + Environment.NewLine + "Please restart the app after loading from the link." + Environment.NewLine + Environment.NewLine + "These links will expire after " + expiry + " minutes."; EmailUtils.CreateEMLFile(user.EmailAddress, "PRS Mobile Configuration Links", emailcontent); } private string CreateURLs(string[] urls) { string URLs = ""; foreach (var url in urls) { URLs = URLs + url + ","; } return URLs + "ENDURLS"; } private BitmapImage? EmailImage(CoreRow? arg) { return PRSDesktop.Resources.email.AsBitmapImage(); } private Dictionary UserGrid_OnEditorValueChanged(object sender, string name, object value) { var editorForm = (IDynamicEditorForm)sender; if (name == nameof(User.TwoFactorAuthenticationType)) { var addressEditor = editorForm.FindEditor(nameof(User.Recipient2FA)); var editor = editorForm.FindEditor(name) as LookupEditorControl; var choice = (TwoFactorAuthenticationType)value; var isGoogle = choice == TwoFactorAuthenticationType.GoogleAuthenticator; addressEditor.SetEnabled(!isGoogle); (editor.EditorDefinition as EnumLookupEditor)!.Buttons[0].SetEnabled(isGoogle); } return new(); } private void UserGrid_OnCustomiseEditor(IDynamicEditorForm sender, User[]? items, DynamicGridColumn column, BaseEditor editor) { var user = items?.FirstOrDefault(); if (user is null) return; if (column.ColumnName == nameof(User.TwoFactorAuthenticationType) && editor is EnumLookupEditor enumEditor) { var qrCodeButton = new EditorButton(user, "View QR Code", 100, ViewQRCode_Click, false); qrCodeButton.SetEnabled(user.TwoFactorAuthenticationType == TwoFactorAuthenticationType.GoogleAuthenticator); enumEditor.Buttons = new[] { qrCodeButton }; } else if (column.ColumnName == nameof(User.Recipient2FA)) { editor.Editable = user.TwoFactorAuthenticationType == TwoFactorAuthenticationType.GoogleAuthenticator ? Editable.Disabled : Editable.Enabled; } } private void ViewQRCode_Click(object editor, object? item) { if (item is User user && user.TwoFactorAuthenticationType == TwoFactorAuthenticationType.GoogleAuthenticator) { var qrWindow = new QR2FAWindow(user); qrWindow.ShowDialog(); } } private bool ToggleDisabledUsers(Button btn, CoreRow[] rows) { ShowAll = !ShowAll; UpdateButton(btn, PRSDesktop.Resources.anonymous.AsBitmapImage(Color.White), ShowAll ? "Hide Finished" : "Show All"); return true; } protected override void Reload(Filters criteria, Columns columns, ref SortOrder? sort, Action action) { if (!ShowAll) criteria.Add(new Filter(x => x.Disabled).IsEqualTo(false)); sort = new SortOrder(x => x.UserID); base.Reload(criteria, columns, ref sort, action); } public override void SaveItem(User item) { base.SaveItem(item); if (item.ID == ClientFactory.UserGuid) Security.Reset(); } private void AfterSave(IDynamicEditorForm editor, BaseObject[] items) { var users = items.Cast().ToArray(); var ids = users.Select(x => x.ID).ToArray(); var linkedEmployees = new Client().Query( new Filter(x => x.UserLink.ID).InList(ids), new Columns(x => x.UserLink.ID) ).Rows.Select(r => r.Get(c=>c.UserLink.ID)).ToArray(); var newEmployees = new List(); foreach (var user in users) { if (!linkedEmployees.Contains(user.ID)) { var result = MessageBox.Show($"{user.UserID} is not associated with an employee. Do you wish to create one?", "Create new Employee?", MessageBoxButton.YesNo); if (result == MessageBoxResult.Yes) { var newEmployee = new Employee() { Name = user.Description }; if(!string.IsNullOrWhiteSpace(user.EmailAddress)) newEmployee.Email = user.EmailAddress; newEmployee.UserLink.ID = user.ID; newEmployee.UserLink.Synchronise(user); var grid = DynamicGridUtils.CreateDynamicGrid(typeof(DynamicDataGrid<>), typeof(Employee)); grid.EditItems(new object[] { newEmployee }); } } } } } }