diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2020-01-19 16:10:55 +0200 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2020-01-19 16:10:55 +0200 |
| commit | 7ffd0bab3c6f397936f8ef9f6829cdf33b850efa (patch) | |
| tree | c2fb5b6cef2d04fe529b284a734657749880abf9 /Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI | |
| parent | 09d432566f696f0eeb3fce97d2c870cfd1c91f89 (diff) | |
| download | Tango-7ffd0bab3c6f397936f8ef9f6829cdf33b850efa.tar.gz Tango-7ffd0bab3c6f397936f8ef9f6829cdf33b850efa.zip | |
Implemented new ms user creation + PASSWORD_CHANGE_REQUIRED.
Improved ms login design + password change.
Improved ms main menu and current user design.
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI')
6 files changed, 219 insertions, 45 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs index 0131cd209..26938b203 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs @@ -147,6 +147,14 @@ namespace Tango.MachineStudio.UI.Authentication }; } + if (response.PasswordChangeRequired) + { + return new AuthenticationLoginResult() + { + Response = response + }; + } + try { ObservablesStaticCollections.Instance.Initialize((x) => diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login_white.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login_white.png Binary files differnew file mode 100644 index 000000000..10a054147 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login_white.png diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index 13f22dfda..0525c2351 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -363,6 +363,7 @@ <Link>TCC\template.bmp</Link> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> + <Resource Include="Images\login_white.png" /> <Resource Include="Images\login.png" /> <Resource Include="Images\active_directory.png" /> <Resource Include="Images\machinestudio_login.png" /> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs index dce469dbd..c00caf72a 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs @@ -22,6 +22,9 @@ using Tango.MachineStudio.UI.Messages; using Tango.Settings; using Tango.SharedUI; using Tango.Web; +using SimpleValidator.Extensions; +using Tango.BL.Entities; +using System.Data.Entity; namespace Tango.MachineStudio.UI.ViewModels { @@ -38,6 +41,7 @@ namespace Tango.MachineStudio.UI.ViewModels private Rfc2898Cryptographer cryptographer; private MachineStudioSettings _settings; private MachineStudioWebClient _machineStudioWebClient; + private TaskCompletionSource<object> _updatePasswordCompletionSource; private String _email; /// <summary> @@ -82,6 +86,14 @@ namespace Tango.MachineStudio.UI.ViewModels set { _isLogging = value; RaisePropertyChangedAuto(); } } + private bool _showLogginDetails; + public bool ShowLoggingDetails + { + get { return _showLogginDetails; } + set { _showLogginDetails = value; RaisePropertyChangedAuto(); } + } + + private bool _rememberMe; /// <summary> /// Gets or sets a value indicating whether to remember the last user email and password. @@ -123,12 +135,38 @@ namespace Tango.MachineStudio.UI.ViewModels set { _progressLog = value; RaisePropertyChangedAuto(); } } + private bool _isChangingPassword; + public bool IsChangingPassword + { + get { return _isChangingPassword; } + set { _isChangingPassword = value; RaisePropertyChangedAuto(); } + } + + private String _newPassword1; + public String NewPassword1 + { + get { return _newPassword1; } + set { _newPassword1 = value; RaisePropertyChangedAuto(); } + } + + private String _newPassword2; + public String NewPassword2 + { + get { return _newPassword2; } + set { _newPassword2 = value; RaisePropertyChangedAuto(); } + } + /// <summary> /// Gets or sets the login command. /// </summary> public RelayCommand LoginCommand { get; set; } /// <summary> + /// Gets or sets the update password command. + /// </summary> + public RelayCommand UpdatePasswordCommand { get; set; } + + /// <summary> /// Initializes a new instance of the <see cref="LoginViewVM"/> class. /// </summary> /// <param name="authenticationProvider">The authentication provider.</param> @@ -137,6 +175,7 @@ namespace Tango.MachineStudio.UI.ViewModels public LoginViewVM(MachineStudioWebClient machineStudioWebClient, IAuthenticationProvider authenticationProvider, INavigationManager navigationManager, INotificationProvider notificationProvider, IEventLogger eventLogger) { EnableSlotSelection = true; + ShowLoggingDetails = true; _machineStudioWebClient = machineStudioWebClient; _settings = SettingsManager.Default.GetOrCreate<MachineStudioSettings>(); @@ -146,6 +185,7 @@ namespace Tango.MachineStudio.UI.ViewModels _authenticationProvider = authenticationProvider; _eventLogger = eventLogger; LoginCommand = new RelayCommand(Login, () => !IsLogging); + UpdatePasswordCommand = new RelayCommand(UpdatePassword, () => IsChangingPassword); cryptographer = new Rfc2898Cryptographer(); Email = _settings.LastLoginEmail; @@ -181,6 +221,10 @@ namespace Tango.MachineStudio.UI.ViewModels try { IsLogging = true; + ShowLoggingDetails = false; + NewPassword1 = String.Empty; + NewPassword2 = String.Empty; + InvalidateRelayCommands(); LoginMethod loginMethod = IsActiveDirectory ? LoginMethod.ActiveDirectory : LoginMethod.StandardUser; @@ -190,9 +234,9 @@ namespace Tango.MachineStudio.UI.ViewModels _settings.DeploymentSlot = DeploymentSlot; LoginResponse result = _authenticationProvider.Login(Email, Password, loginMethod, _settings.ByPassEnvironmentVersionCheck, (progress) => - { - ProgressLog = progress; - }).Response; + { + ProgressLog = progress; + }).Response; if (result.VersionChangeRequired && !_settings.ByPassEnvironmentVersionCheck) { @@ -211,6 +255,14 @@ namespace Tango.MachineStudio.UI.ViewModels return; } + if (result.PasswordChangeRequired) + { + StartUpdatePassword().Task.GetAwaiter().GetResult(); + Password = NewPassword1; + Login(); + return; + } + _eventLogger.Log(EventTypes.APPLICATION_STARTED, "Application Started!"); _navigationManager.NavigateTo(NavigationView.MainView); @@ -224,19 +276,94 @@ namespace Tango.MachineStudio.UI.ViewModels _eventLogger.Log("User logged in."); EnableSlotSelection = false; + + IsLogging = false; + ShowLoggingDetails = true; + IsChangingPassword = false; + InvalidateRelayCommands(); }); } catch (Exception ex) { + IsLogging = false; + ShowLoggingDetails = true; + IsChangingPassword = false; + InvalidateRelayCommands(); LogManager.Log(ex, "Login Error."); _notificationProvider.ShowError($"An error occurred while trying to perform the log-in operation.\n{ex.FlattenMessage()}"); } - finally + } + } + + private TaskCompletionSource<object> StartUpdatePassword() + { + _updatePasswordCompletionSource = new TaskCompletionSource<object>(); + + IsChangingPassword = true; + ShowLoggingDetails = false; + IsLogging = false; + InvalidateRelayCommands(); + + return _updatePasswordCompletionSource; + } + + private async void UpdatePassword() + { + await Task.Factory.StartNew(() => + { + try + { + if (!Validate()) + { + return; + } + + ProgressLog = "Updating your password..."; + IsChangingPassword = false; + IsLogging = true; + InvalidateRelayCommands(); + + using (var db = ObservablesContext.CreateDefault()) + { + var user = db.Users.SingleOrDefault(x => x.Email == Email); + user.PasswordChangeRequired = false; + user.Password = User.GetPasswordHash(NewPassword1); + db.SaveChanges(); + } + + _updatePasswordCompletionSource.SetResult(true); + } + catch (Exception ex) { IsLogging = false; + IsChangingPassword = false; + ShowLoggingDetails = true; + InvalidateRelayCommands(); + _updatePasswordCompletionSource.SetException(ex); + } + finally + { InvalidateRelayCommands(); } + }); + } + + protected override void OnValidating() + { + if (IsChangingPassword) + { + if (!NewPassword1.IsBetweenLength(6, 8)) + { + InsertError(nameof(NewPassword1), "Password must be 6 to 8 characters long"); + } + + if (NewPassword1 != NewPassword2) + { + InsertError(nameof(NewPassword2), "Passwords do not match"); + } } + + base.OnValidating(); } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml index ff13ec2c7..9a3b3405e 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml @@ -47,7 +47,7 @@ </StackPanel> <Grid> - <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="-600 110 0 0" Visibility="{Binding IsLogging,Converter={StaticResource BooleanToVisibilityInverseConverter}}"> + <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="-600 110 0 0" Visibility="{Binding ShowLoggingDetails,Converter={StaticResource BooleanToVisibilityConverter}}"> <RadioButton ToolTip="Login using your an active directory account" IsChecked="{Binding IsActiveDirectory}" FontSize="16" VerticalContentAlignment="Center" Padding="10 0 0 0"> <Image Source="/Images/active_directory.png" Stretch="Uniform" Height="80" RenderOptions.BitmapScalingMode="Fant" /> </RadioButton> @@ -57,10 +57,36 @@ </StackPanel> <DockPanel HorizontalAlignment="Center" VerticalAlignment="Center" Width="320" Margin="0 120 0 0" Height="510"> - <Button DockPanel.Dock="Bottom" AutomationProperties.AutomationId="{x:Static automation:UI.LoginButton}" Margin="25 20 0 0" Height="50" Command="{Binding LoginCommand}" Content="LOGIN"></Button> + <Grid DockPanel.Dock="Bottom" Margin="25 20 0 0" > + <Button AutomationProperties.AutomationId="{x:Static automation:UI.LoginButton}" Height="50" Command="{Binding LoginCommand}" Content="LOGIN"> + <Button.Style> + <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}"> + <Setter Property="Visibility" Value="Visible"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding IsChangingPassword}" Value="True"> + <Setter Property="Visibility" Value="Hidden"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Button.Style> + </Button> + + <Button AutomationProperties.AutomationId="{x:Static automation:UI.LoginButton}" Height="50" Command="{Binding UpdatePasswordCommand}" Content="CHANGE PASSWORD"> + <Button.Style> + <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}"> + <Setter Property="Visibility" Value="Hidden"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding IsChangingPassword}" Value="True"> + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Button.Style> + </Button> + </Grid> <Grid> - <StackPanel Visibility="{Binding IsLogging,Converter={StaticResource BooleanToVisibilityInverseConverter}}"> + <StackPanel Visibility="{Binding ShowLoggingDetails,Converter={StaticResource BooleanToVisibilityConverter}}"> <TextBlock HorizontalAlignment="Center" FontSize="24">Login to your account</TextBlock> <Image Source="/Images/login.png" RenderOptions.BitmapScalingMode="Fant" Width="100" Margin="0 20 0 0"></Image> <DockPanel Margin="0 20 0 0"> @@ -97,6 +123,19 @@ </Grid> <TextBlock HorizontalAlignment="Center" Margin="0 30 0 0" FontSize="16" FontStyle="Italic" Foreground="{StaticResource GrayBrush200}" Text="{Binding ProgressLog}"></TextBlock> </StackPanel> + + <StackPanel Visibility="{Binding IsChangingPassword,Converter={StaticResource BooleanToVisibilityConverter}}"> + <TextBlock HorizontalAlignment="Center" FontSize="24">Password change required</TextBlock> + <Image Source="/Images/login.png" RenderOptions.BitmapScalingMode="Fant" Width="100" Margin="0 20 0 0"></Image> + <DockPanel Margin="0 40 0 0"> + <materialDesign:PackIcon Margin="0 0 0 0" Width="20" Height="20" VerticalAlignment="Top" Foreground="{Binding ElementName=txtNewPass1, Path=BorderBrush}" Kind="Key" /> + <PasswordBox x:Name="txtNewPass1" helpers:PasswordHelper.Attach="True" helpers:PasswordHelper.Password="{Binding NewPassword1,Mode=TwoWay,UpdateSourceTrigger=LostFocus,NotifyOnValidationError=True,ValidatesOnDataErrors=True,ValidatesOnNotifyDataErrors=True}" Margin="5 0 0 0" materialDesign:HintAssist.FloatingScale="0.50" materialDesign:HintAssist.Hint="New Password" materialDesign:TextFieldAssist.TextBoxViewMargin="1 0 1 0" FontSize="20" Style="{StaticResource MaterialDesignFloatingHintPasswordBox}" AutomationProperties.IsRequiredForForm="True" /> + </DockPanel> + <DockPanel Margin="0 40 0 0"> + <materialDesign:PackIcon Margin="0 0 0 0" Width="20" Height="20" VerticalAlignment="Top" Foreground="{Binding ElementName=txtNewPass2, Path=BorderBrush}" Kind="Key" /> + <PasswordBox x:Name="txtNewPass2" helpers:PasswordHelper.Attach="True" helpers:PasswordHelper.Password="{Binding NewPassword2,Mode=TwoWay,UpdateSourceTrigger=LostFocus,NotifyOnValidationError=True,ValidatesOnDataErrors=True,ValidatesOnNotifyDataErrors=True}" Margin="5 0 0 0" materialDesign:HintAssist.FloatingScale="0.50" materialDesign:HintAssist.Hint="Confirm Password" materialDesign:TextFieldAssist.TextBoxViewMargin="1 0 1 0" FontSize="20" Style="{StaticResource MaterialDesignFloatingHintPasswordBox}" AutomationProperties.IsRequiredForForm="True" /> + </DockPanel> + </StackPanel> </Grid> </DockPanel> </Grid> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index 48f7b46d3..2d5a5c3aa 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -50,48 +50,19 @@ <DockPanel LastChildFill="False" TextElement.Foreground="{StaticResource MainWindow.Foreground}" > <StackPanel MinWidth="300" DockPanel.Dock="Top"> <Grid> + <Button Foreground="{StaticResource BlackBrush}" Style="{StaticResource MaterialDesignFlatButton}" Command="{Binding HomeCommand}" HorizontalAlignment="Left" HorizontalContentAlignment="Left" Margin="5 10 0 0" Width="200" Height="40" Padding="5 8 8 8"> + <StackPanel Orientation="Horizontal"> + <materialDesign:PackIcon VerticalAlignment="Center" Kind="Home" Width="32" Height="32"></materialDesign:PackIcon> + <TextBlock FontSize="16" VerticalAlignment="Center" Margin="10 0 0 0">Home</TextBlock> + </StackPanel> + </Button> + <ToggleButton Style="{StaticResource MaterialDesignHamburgerToggleButton}" HorizontalAlignment="Right" Margin="16" IsChecked="{Binding Source={x:Reference MenuToggleButton}, Path=IsChecked, Mode=TwoWay}" /> - - <StackPanel Margin="5 0 0 0" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center"> - <Image Source="/Images/login.png" RenderOptions.BitmapScalingMode="Fant" VerticalAlignment="Center" Width="50" Height="50"></Image> - <StackPanel Margin="0 5 0 0"> - <TextBlock FontSize="16" TextTrimming="CharacterEllipsis" MaxWidth="170" FontStyle="Italic" FontWeight="Bold" Margin="10 0 0 0" VerticalAlignment="Center" Text="{Binding AuthenticationProvider.CurrentUser.Contact.FullName}"></TextBlock> - <TextBlock FontSize="12" TextTrimming="CharacterEllipsis" MaxWidth="170" FontStyle="Italic" Margin="10 5 0 0" VerticalAlignment="Center"> - <Run Text="{Binding AuthenticationProvider.CurrentUser.Organization.Name}"></Run> - , - <Run Text="{Binding AuthenticationProvider.CurrentUser.Roles[0].Name}"> - <Run.ToolTip> - <ItemsControl ItemsSource="{Binding AuthenticationProvider.CurrentUser.Roles}"> - <ItemsControl.ItemTemplate> - <DataTemplate> - <StackPanel Orientation="Horizontal" Margin="2"> - <materialDesign:PackIcon Kind="AccountKey" Width="16" Height="16" /> - <TextBlock Margin="5 0 0 0" Text="{Binding Name}"></TextBlock> - </StackPanel> - </DataTemplate> - </ItemsControl.ItemTemplate> - </ItemsControl> - </Run.ToolTip> - </Run> - <Run>...</Run> - </TextBlock> - </StackPanel> - </StackPanel> </Grid> <StackPanel Margin="0 16 0 0"> - <ListBoxItem> - <i:Interaction.Triggers> - <i:EventTrigger EventName="PreviewMouseUp"> - <i:InvokeCommandAction Command="{Binding HomeCommand}"></i:InvokeCommandAction> - </i:EventTrigger> - </i:Interaction.Triggers> - <StackPanel Orientation="Horizontal"> - <materialDesign:PackIcon VerticalAlignment="Center" Kind="Home" Width="32" Height="32"></materialDesign:PackIcon> - <TextBlock FontSize="16" VerticalAlignment="Center" Margin="10 0 0 0">Home</TextBlock> - </StackPanel> - </ListBoxItem> + </StackPanel> <StackPanel Margin="10 10 0 0"> <TextBlock Foreground="{StaticResource borderBrush}" FontSize="16" FontWeight="Bold" FontStyle="Italic">MODULES</TextBlock> @@ -148,8 +119,36 @@ <materialDesign:ColorZone Padding="16" materialDesign:ShadowAssist.ShadowDepth="Depth2" Mode="PrimaryMid" DockPanel.Dock="Top" Background="{StaticResource MainWindow.Header}"> <DockPanel> - <ToggleButton Style="{StaticResource MaterialDesignHamburgerToggleButton}" IsChecked="{Binding IsMenuOpened}" + <StackPanel Orientation="Horizontal"> + <ToggleButton VerticalAlignment="Center" Style="{StaticResource MaterialDesignHamburgerToggleButton}" IsChecked="{Binding IsMenuOpened}" x:Name="MenuToggleButton"/> + + <StackPanel Margin="10 0 0 0" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center"> + <Image Source="/Images/login_white.png" RenderOptions.BitmapScalingMode="Fant" VerticalAlignment="Center" Width="50" Height="50"></Image> + <StackPanel Margin="0 5 0 0"> + <TextBlock FontSize="16" TextTrimming="CharacterEllipsis" MaxWidth="170" FontStyle="Italic" FontWeight="Bold" Margin="10 0 0 0" VerticalAlignment="Center" Text="{Binding AuthenticationProvider.CurrentUser.Contact.FullName}"></TextBlock> + <TextBlock FontSize="12" TextTrimming="CharacterEllipsis" MaxWidth="170" FontStyle="Italic" Margin="10 5 0 0" VerticalAlignment="Center"> + <Run Text="{Binding AuthenticationProvider.CurrentUser.Organization.Name}"></Run> + , + <Run Text="{Binding AuthenticationProvider.CurrentUser.Roles[0].Name}"> + <Run.ToolTip> + <ItemsControl ItemsSource="{Binding AuthenticationProvider.CurrentUser.Roles}"> + <ItemsControl.ItemTemplate> + <DataTemplate> + <StackPanel Orientation="Horizontal" Margin="2"> + <materialDesign:PackIcon Kind="AccountKey" Width="16" Height="16" /> + <TextBlock Margin="5 0 0 0" Text="{Binding Name}"></TextBlock> + </StackPanel> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </Run.ToolTip> + </Run> + <Run>...</Run> + </TextBlock> + </StackPanel> + </StackPanel> + </StackPanel> <materialDesign:PopupBox DockPanel.Dock="Right" PlacementMode="BottomAndAlignRightEdges" StaysOpen="False" > <StackPanel> <Button Command="{Binding ConnectCommand}"> |
