├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── CodeCoverage.runsettings
├── Directory.Build.targets
├── IntegrationTests.playlist
├── LICENSE
├── README.md
├── UnitTests.playlist
├── UserManager.BusinessLogic.Tests
├── DataAccess
│ ├── DatabaseServiceTests.cs
│ └── Mappers
│ │ ├── EmailMapperTests.cs
│ │ └── RoleMapperTests.cs
├── Model
│ ├── EmailAttributeTests.cs
│ ├── EmailTests.cs
│ └── RoleTests.cs
├── Properties
│ └── AssemblyInfo.cs
├── UserManager.BusinessLogic.Tests.csproj
└── packages.config
├── UserManager.BusinessLogic
├── DataAccess
│ ├── ConfigureDapper.cs
│ ├── DapperExtensions.cs
│ ├── DatabaseContext.cs
│ ├── DatabaseService.cs
│ ├── IDatabaseService.cs
│ ├── Mappers
│ │ ├── EmailMapper.cs
│ │ ├── IntTypeHandler.cs
│ │ └── RoleMapper.cs
│ └── Repositories
│ │ ├── DatabaseRepository.cs
│ │ ├── IDatabaseRepository.cs
│ │ ├── IRoleRepository.cs
│ │ ├── IUserRepository.cs
│ │ ├── RoleRepository.cs
│ │ └── UserRepository.cs
├── Exceptions
│ └── NotFoundException.cs
├── Extensions
│ └── LogExtensions.cs
├── Model
│ ├── Email.cs
│ ├── EmailAttribute.cs
│ ├── Role.cs
│ └── User.cs
├── Properties
│ └── AssemblyInfo.cs
├── UserManager.BusinessLogic.csproj
└── packages.config
├── UserManager.DataAccess.Migrations
├── App.config
├── Command.cs
├── FluentMigratorExtensions.cs
├── Migrations
│ ├── 20201024202704_InitialMigration.cs
│ ├── 20201024202825_AddUserTable.cs
│ ├── 20201113194828_AddRoleToUser.cs
│ └── 20210114223404_AddCreationDateToUser.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── UserManager.DataAccess.Migrations.csproj
└── packages.config
├── UserManager.IntegrationTests
├── Main
│ ├── MainMenuTests.cs
│ └── SettingsMenuTests.cs
├── Properties
│ └── AssemblyInfo.cs
├── TestUtils
│ ├── AppWindow.cs
│ ├── Initialize.cs
│ └── TestBase.cs
├── UserManager.IntegrationTests.csproj
├── Users
│ ├── BaseUserView.cs
│ ├── UserCreationTests.cs
│ └── UserListTests.cs
└── packages.config
├── UserManager.Resources
├── General.Designer.cs
├── General.es.Designer.cs
├── General.es.resx
├── General.resx
├── Properties
│ └── AssemblyInfo.cs
└── UserManager.Resources.csproj
├── UserManager.Tests
├── Mappers
│ ├── RoleProfileTests.cs
│ └── UserProfileTests.cs
├── Properties
│ └── AssemblyInfo.cs
├── Startup
│ └── ExecutionParametersTests.cs
├── TestUtils
│ ├── ArgExt.cs
│ ├── Fakes
│ │ └── FakeSnackbarMessage.cs
│ ├── IMessageHubExtensions.cs
│ ├── MappingAssertions.cs
│ ├── ObjectComparer.cs
│ ├── PropertyChangeListener.cs
│ └── TestMapperProfile.cs
├── UserManager.Tests.csproj
├── ViewModels
│ ├── CreateUserViewModelTests.cs
│ ├── MainViewModelTests.cs
│ ├── RolesViewModelTests.cs
│ └── UsersViewModelTests.cs
├── app.config
└── packages.config
├── UserManager.sln
├── UserManager
├── App.config
├── DTOs
│ ├── CreateUserDto.cs
│ ├── DatabaseConnectionDto.cs
│ ├── LanguageDto.cs
│ ├── RoleListItemDto.cs
│ ├── RoleSelectDto.cs
│ └── UserListItemDto.cs
├── Events
│ └── UserCreatedEvent.cs
├── Mappers
│ ├── RoleProfile.cs
│ └── UserProfile.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── Providers
│ ├── ISettingProvider.cs
│ └── SettingProvider.cs
├── Startup
│ ├── AutomapperConfig.cs
│ ├── ExceptionHandling.cs
│ ├── ExecutionParameters.cs
│ ├── GlobalizationConfig.cs
│ ├── IoCConfig.cs
│ ├── LogConfig.cs
│ └── TelemetryConfig.cs
├── UserManager.csproj
├── ViewModels
│ ├── CreateUserViewModel.cs
│ ├── MainViewModel.cs
│ ├── RolesViewModel.cs
│ └── UsersViewModel.cs
├── Views
│ ├── CreateUserView.Designer.cs
│ ├── CreateUserView.cs
│ ├── CreateUserView.resx
│ ├── MainView.Designer.cs
│ ├── MainView.cs
│ ├── MainView.resx
│ ├── RolesView.Designer.cs
│ ├── RolesView.cs
│ ├── RolesView.resx
│ ├── UsersView.Designer.cs
│ ├── UsersView.cs
│ └── UsersView.resx
└── packages.config
├── WinformsTools.Common.Tests
├── Extensions
│ ├── CollectionExtensionsTests.cs
│ └── PropertyInfoExtensionsTests.cs
├── Helpers
│ └── MagicToolboxTests.cs
├── Properties
│ └── AssemblyInfo.cs
├── SystemContextTests.cs
├── WinformsTools.Common.Tests.csproj
└── packages.config
├── WinformsTools.Common
├── Extensions
│ ├── CollectionExtensions.cs
│ └── PropertyInfoExtensions.cs
├── Helpers
│ ├── AsyncHelper.cs
│ └── MagicToolbox.cs
├── Properties
│ └── AssemblyInfo.cs
├── SystemContext.cs
└── WinformsTools.Common.csproj
├── WinformsTools.IntegrationTestUtils.Tests
├── Elements
│ └── DialogResultMapperTests.cs
├── Properties
│ └── AssemblyInfo.cs
├── WinformsTools.IntegrationTestUtils.Tests.csproj
└── packages.config
├── WinformsTools.IntegrationTestUtils
├── BaseAppWindow.cs
├── ElementNotFoundException.cs
├── Elements
│ ├── DialogOption.cs
│ ├── DialogResultMapper.cs
│ ├── ModalElement.cs
│ └── VisualForm.cs
├── Extensions
│ ├── AutomationElementQueryExtensions.cs
│ ├── CustomLocalizedStrings.cs
│ ├── DataGridViewExtensions.cs
│ └── FlaUiExtensions.cs
├── Properties
│ └── AssemblyInfo.cs
├── WinformsTools.IntegrationTestUtils.csproj
└── packages.config
├── WinformsTools.MVVM.Tests
├── Bindings
│ ├── AdvancedBindingListTests.cs
│ ├── ListObjectComparerTests.cs
│ └── ReflectionUtilsTests.cs
├── Controls
│ ├── ControlExtensionsTests.cs
│ └── DataGridViewControl
│ │ ├── BindedAdvancedDataGridViewTests.cs
│ │ ├── FilterClauseTests.cs
│ │ └── FilterConverterTests.cs
├── Core
│ └── CommandTests.cs
├── Navigation
│ ├── RegisteredViewsTests.cs
│ ├── ViewClosedEventTests.cs
│ └── ViewNavigatorTests.cs
├── Properties
│ └── AssemblyInfo.cs
├── Telemetry
│ ├── ClickMetricTests.cs
│ ├── MetricsTests.cs
│ └── ViewEnteredMetricTests.cs
├── TestUtils
│ ├── DataGridViewExtensions.cs
│ ├── Fakes
│ │ ├── FakeView.cs
│ │ └── FakeViewModel.cs
│ └── SerilogFormatter.cs
├── WinformsTools.MVVM.Tests.csproj
├── app.config
└── packages.config
└── WinformsTools.MVVM
├── Bindings
├── AdvancedBindingList.cs
├── Bind.cs
├── BindableObject.cs
├── BindingExtensions.cs
├── ClickBindingExtensions.cs
├── ComboBoxExtensions.cs
├── ComboBoxSource.cs
├── ConversionBinding.cs
├── Converters
│ └── InverseBoolConverter.cs
├── DataGridViewBindingExtensions.cs
├── ListObjectComparer.cs
├── PropertyComparer.cs
└── ReflectionUtils.cs
├── Components
├── ApplicationDispatcher.cs
├── GenericValidator.cs
├── IMessageDialog.cs
└── MessageDialog.cs
├── Controls
├── BindableToolStripMenuItem.cs
├── ControlExtensions.cs
├── DataGridViewControl
│ ├── FilterClause.cs
│ ├── FilterConverter.cs
│ └── TableColumnAttribute.cs
├── IMenuOption.cs
├── IconExtensions.cs
├── MenuOption.cs
└── SnackbarControl
│ ├── SnackbarControl.Designer.cs
│ ├── SnackbarControl.cs
│ ├── SnackbarControl.resx
│ ├── SnackbarMessage.cs
│ ├── SnackbarMessageProvider.cs
│ └── SnackbarProvider.cs
├── Core
├── Command.cs
├── ICommand.cs
├── IView.cs
└── IViewModel.cs
├── DependencyInjection
├── GreediestConstructorBehavior.cs
└── SimpleInjectorExtensions.cs
├── Navigation
├── IViewNavigator.cs
├── RegisteredViews.cs
├── ViewClosedEvent.cs
└── ViewNavigator.cs
├── Properties
└── AssemblyInfo.cs
├── Telemetry
├── ClickMetric.cs
├── IMetric.cs
├── Metrics.cs
└── ViewEnteredMetric.cs
├── Validations
└── Validation.cs
├── WinformsTools.MVVM.csproj
└── packages.config
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - master
8 | pull_request:
9 | branches:
10 | - master
11 |
12 | env:
13 | SOLUTION_NAME: UserManager.sln
14 |
15 | jobs:
16 | build:
17 | runs-on: windows-latest
18 |
19 | steps:
20 | - name: Checkout
21 | uses: actions/checkout@v2
22 |
23 | - name: Setup MSBuild
24 | uses: microsoft/setup-msbuild@v1
25 |
26 | - name: Setup NuGet
27 | uses: NuGet/setup-nuget@v1.0.5
28 |
29 | - name: Restore NuGet packages
30 | run: nuget restore ${{ env.SOLUTION_NAME }}
31 |
32 | - name: Build solution
33 | run: msbuild ${{ env.SOLUTION_NAME }} /verbosity:quiet /p:Configuration=Release
34 |
35 | - name: Setup VSTest
36 | uses: darenm/Setup-VSTest@v1
37 |
38 | - name: Run Unit tests
39 | run: vstest.console.exe **/bin/**/*.Tests.dll /TestCaseFilter:"TestCategory=UnitTests" /Parallel /Logger:"trx"
40 |
41 | - name: Publish test results
42 | uses: dorny/test-reporter@v1
43 | if: success() || failure()
44 | with:
45 | name: Unit Tests
46 | path: TestResults/*.trx
47 | reporter: dotnet-trx
48 |
--------------------------------------------------------------------------------
/CodeCoverage.runsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | .*WinformsTools[\w|\d|\.|-]*\.dll$
12 | .*UserManager[\w|\d|\.|-]*\.dll$
13 | .*UserManager.exe$
14 |
15 |
16 | .*Tests.dll$
17 | .*TestUtils.dll$
18 |
19 |
20 |
21 |
22 | .*\\*.Designer.cs
23 |
24 |
25 |
26 |
27 |
28 | ^System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute$
29 |
30 |
31 |
32 |
33 | True
34 | True
35 | True
36 | False
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 | ..\TestResults
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/IntegrationTests.playlist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 A Bravo Dev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/UnitTests.playlist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic.Tests/DataAccess/Mappers/EmailMapperTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using System;
4 | using System.ComponentModel.DataAnnotations;
5 | using System.Data.SqlClient;
6 | using UserManager.BusinessLogic.DataAccess.Mappers;
7 | using UserManager.BusinessLogic.Model;
8 |
9 | namespace UserManager.BusinessLogic.Tests.DataAccess.Mappers
10 | {
11 | [TestClass]
12 | public class EmailMapperTests
13 | {
14 | [TestMethod]
15 | public void Parse_Null_ReturnNull()
16 | {
17 | // Arrange
18 | var mapper = new EmailMapper();
19 |
20 | // Act
21 | var email = mapper.Parse(null);
22 |
23 | // Assert
24 | email.Should().BeNull();
25 | }
26 |
27 | [TestMethod]
28 | public void Parse_ValidEmail_ReturnParsedEmail()
29 | {
30 | // Arrange
31 | var emailAddress = "valid_email@mail.com";
32 | var mapper = new EmailMapper();
33 |
34 | // Act
35 | var email = mapper.Parse(emailAddress);
36 |
37 | // Assert
38 | email.ToString().Should().Be(emailAddress);
39 | }
40 |
41 | [TestMethod]
42 | public void Parse_InvalidEmail_ThrowException()
43 | {
44 | // Arrange
45 | var emailAddress = "invalid_email";
46 | var mapper = new EmailMapper();
47 |
48 | // Act
49 | Action action = () => mapper.Parse(emailAddress);
50 |
51 | // Assert
52 | action.Should().Throw();
53 | }
54 |
55 | [TestMethod]
56 | public void SetValue_AnyEmail_SetEmailToParameter()
57 | {
58 | // Arrange
59 | var emailAddress = "valid_email@mail.com";
60 | var email = new Email(emailAddress);
61 | var mapper = new EmailMapper();
62 | var parameter = new SqlParameter();
63 |
64 | // Act
65 | mapper.SetValue(parameter, email);
66 |
67 | // Assert
68 | parameter.Value.Should().Be(emailAddress);
69 | }
70 |
71 | [TestMethod]
72 | public void SetValue_Null_SetNullToParameter()
73 | {
74 | // Arrange
75 | var mapper = new EmailMapper();
76 | var parameter = new SqlParameter();
77 |
78 | // Act
79 | mapper.SetValue(parameter, null);
80 |
81 | // Assert
82 | parameter.Value.Should().Be(DBNull.Value);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic.Tests/DataAccess/Mappers/RoleMapperTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using System;
4 | using System.Data.SqlClient;
5 | using UserManager.BusinessLogic.DataAccess.Mappers;
6 | using UserManager.BusinessLogic.Model;
7 |
8 | namespace UserManager.BusinessLogic.Tests.DataAccess.Mappers
9 | {
10 | [TestClass]
11 | public class RoleMapperTests
12 | {
13 | [TestMethod]
14 | public void Parse_Null_ReturnNull()
15 | {
16 | // Arrange
17 | var mapper = new RoleMapper();
18 |
19 | // Act
20 | var role = mapper.Parse(null);
21 |
22 | // Assert
23 | role.Should().BeNull();
24 | }
25 |
26 | [TestMethod]
27 | public void Parse_ValidRole_ReturnParsedRole()
28 | {
29 | // Arrange
30 | var validRole = Role.Basic;
31 | var mapper = new RoleMapper();
32 |
33 | // Act
34 | var role = mapper.Parse(validRole.Id);
35 |
36 | // Assert
37 | role.Should().Be(validRole);
38 | }
39 |
40 | [TestMethod]
41 | public void Parse_InvalidEmail_ThrowException()
42 | {
43 | // Arrange
44 | var roleId = 0;
45 | var mapper = new RoleMapper();
46 |
47 | // Act
48 | Action action = () => mapper.Parse(roleId);
49 |
50 | // Assert
51 | action.Should().Throw();
52 | }
53 |
54 | [TestMethod]
55 | public void SetValue_AnyRole_SetRoleIdToParameter()
56 | {
57 | // Arrange
58 | var validRole = Role.Basic;
59 | var mapper = new RoleMapper();
60 | var parameter = new SqlParameter();
61 |
62 | // Act
63 | mapper.SetValue(parameter, validRole);
64 |
65 | // Assert
66 | parameter.Value.Should().Be(validRole.Id);
67 | }
68 |
69 | [TestMethod]
70 | public void SetValue_Null_SetNullToParameter()
71 | {
72 | // Arrange
73 | var mapper = new RoleMapper();
74 | var parameter = new SqlParameter();
75 |
76 | // Act
77 | mapper.SetValue(parameter, null);
78 |
79 | // Assert
80 | parameter.Value.Should().Be(DBNull.Value);
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic.Tests/Model/EmailAttributeTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel.DataAnnotations;
6 | using UserManager.BusinessLogic.Model;
7 |
8 | namespace UserManager.BusinessLogic.Tests.Model
9 | {
10 |
11 | [TestClass]
12 | public class EmailAttributeTests
13 | {
14 | private class UserWithMandatoryEmail
15 | {
16 | [Email]
17 | [Required]
18 | public string Email { get; set; }
19 | }
20 |
21 | private class UserWithOptionalEmail
22 | {
23 | [Email]
24 | public string Email { get; set; }
25 | }
26 |
27 | private class UserWithWrongType
28 | {
29 | [Email]
30 | public int Email { get; set; }
31 | }
32 |
33 | [TestMethod]
34 | public void IsValid_UserWithWrongType_ThrowArgumentException()
35 | {
36 | // Arrange
37 | var user = new UserWithWrongType { Email = 0 };
38 |
39 | // Act
40 | Action action = () => ValidateModel(user);
41 |
42 | // Assert
43 | action.Should().Throw();
44 | }
45 |
46 | [DataTestMethod]
47 | [DataRow(null, false)]
48 | [DataRow("", false)]
49 | [DataRow("valid_email@mail.com", true)]
50 | public void IsValid_UserNeedsEmail_ReturnsTrueIfAValidOne(string emailAddress, bool expectedValidity)
51 | {
52 | // Arrange
53 | var user = new UserWithMandatoryEmail { Email = emailAddress };
54 |
55 | // Act
56 | var (isValid, _) = ValidateModel(user);
57 |
58 | // Assert
59 | isValid.Should().Be(expectedValidity);
60 | }
61 |
62 | [DataTestMethod]
63 | [DataRow(null, true)]
64 | [DataRow("", false)]
65 | [DataRow("valid_email@mail.com", true)]
66 | public void IsValid_UserDoesNotNeedEmail_ReturnsTrueIfAValidOneOrNotProvided(string emailAddress, bool expectedValidity)
67 | {
68 | // Arrange
69 | var user = new UserWithOptionalEmail { Email = emailAddress };
70 |
71 | // Act
72 | var (isValid, _) = ValidateModel(user);
73 |
74 | // Assert
75 | isValid.Should().Be(expectedValidity);
76 | }
77 |
78 | private (bool IsValid, List Results) ValidateModel(object model)
79 | {
80 | var context = new ValidationContext(model);
81 | var results = new List();
82 | var isValid = Validator.TryValidateObject(model, context, results, true);
83 | return (isValid, results);
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic.Tests/Model/EmailTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using System;
4 | using System.ComponentModel.DataAnnotations;
5 | using UserManager.BusinessLogic.Model;
6 |
7 | namespace UserManager.BusinessLogic.Tests.Model
8 | {
9 | [TestClass]
10 | public class EmailTests
11 | {
12 | [TestMethod]
13 | public void Constructor_InvalidEmail_ThrowValidationException()
14 | {
15 | // Arrange
16 | var invalidEmailAddress = "invalid_email";
17 |
18 | // Act
19 | Action action = () => new Email(invalidEmailAddress);
20 |
21 | // Assert
22 | action.Should().Throw();
23 | }
24 |
25 | [DataTestMethod]
26 | [DataRow("valid_email@mail.com")]
27 | [DataRow("valid.email@mail.com")]
28 | [DataRow("valid_email@mail.info")]
29 | [DataRow("valid_email@subdomain.mail.info")]
30 | public void Constructor_ValidEmail_ReturnCreatedEmail(string validEmailAddress)
31 | {
32 | // Act
33 | var email = new Email(validEmailAddress);
34 |
35 | // Assert
36 | email.ToString().Should().Be(validEmailAddress);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic.Tests/Model/RoleTests.cs:
--------------------------------------------------------------------------------
1 | using FluentAssertions;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using System;
4 | using UserManager.BusinessLogic.Model;
5 |
6 | namespace UserManager.BusinessLogic.Tests.Model
7 | {
8 | [TestClass]
9 | public class RoleTests
10 | {
11 | [TestMethod]
12 | public void FromId_WrongId_ThrowException()
13 | {
14 | // Arrange
15 | var wrongRoleId = 0;
16 |
17 | // Act
18 | Action action = () => Role.FromId(wrongRoleId);
19 |
20 | // Assert
21 | action.Should().Throw();
22 | }
23 |
24 | [DataTestMethod]
25 | [DataRow(1)]
26 | [DataRow(2)]
27 | public void FromId_ExistingId_ReturnRole(int roleId)
28 | {
29 | // Act
30 | var role = Role.FromId(roleId);
31 |
32 | // Assert
33 | role.Id.Should().Be(roleId);
34 | }
35 |
36 | [TestMethod]
37 | public void Roles_ReturnTheListOfRoles()
38 | {
39 | // Act
40 | var roles = Role.Roles;
41 |
42 | // Assert
43 | roles.Should().BeEquivalentTo(new[] { Role.Admin, Role.Basic });
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using System.Reflection;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | [assembly: AssemblyTitle("UserManager.BusinessLogic.Tests")]
7 | [assembly: AssemblyDescription("")]
8 | [assembly: AssemblyConfiguration("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("UserManager.BusinessLogic.Tests")]
11 | [assembly: AssemblyCopyright("Copyright © 2021")]
12 | [assembly: AssemblyTrademark("")]
13 | [assembly: AssemblyCulture("")]
14 |
15 | [assembly: ComVisible(false)]
16 |
17 | [assembly: Guid("d59ea9a6-62bf-45c1-af5a-1e73c5d432f6")]
18 |
19 | // [assembly: AssemblyVersion("1.0.*")]
20 | [assembly: AssemblyVersion("1.0.0.0")]
21 | [assembly: AssemblyFileVersion("1.0.0.0")]
22 |
23 | [assembly: TestCategory("UnitTests")]
--------------------------------------------------------------------------------
/UserManager.BusinessLogic.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/ConfigureDapper.cs:
--------------------------------------------------------------------------------
1 | using Dapper;
2 | using UserManager.BusinessLogic.DataAccess.Mappers;
3 |
4 | namespace UserManager.BusinessLogic.DataAccess
5 | {
6 | public static class ConfigureDapper
7 | {
8 | public static void Config()
9 | {
10 | ConfigureMappers();
11 | }
12 |
13 | private static void ConfigureMappers()
14 | {
15 | SqlMapper.AddTypeHandler(new EmailMapper());
16 | SqlMapper.AddTypeHandler(new RoleMapper());
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/DapperExtensions.cs:
--------------------------------------------------------------------------------
1 | using Dapper;
2 | using Newtonsoft.Json;
3 | using System.Collections.Generic;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using UserManager.BusinessLogic.Exceptions;
8 |
9 | namespace UserManager.BusinessLogic.DataAccess
10 | {
11 | public static class DapperExtensions
12 | {
13 | public static async Task> ToListAsync(this Task> source)
14 | => (await source).ToList();
15 |
16 | public static async Task FirstOrDefaultAsync(this Task> source)
17 | => (await source).FirstOrDefault();
18 |
19 | ///
20 | /// Execute query to return first element. It throws if not found
21 | ///
22 | ///
23 | ///
24 | ///
25 | ///
26 | ///
27 | ///
28 | ///
29 | ///
30 | public static async Task GetFirstAsync(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
31 | {
32 | var item = await cnn.QueryFirstOrDefaultAsync(sql, param, transaction, commandTimeout, commandType);
33 | if(item == null)
34 | {
35 | throw new NotFoundException($"{typeof(TSource).Name} not found {JsonConvert.SerializeObject(param)}");
36 | }
37 | return item;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/DatabaseContext.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using System.Data.SqlClient;
3 |
4 | namespace UserManager.BusinessLogic.DataAccess
5 | {
6 | public class DatabaseContext
7 | {
8 | private readonly string _connectionString;
9 |
10 | public DatabaseContext(string conectionString)
11 | {
12 | _connectionString = conectionString;
13 | }
14 |
15 | public virtual SqlConnectionStringBuilder ConnectionInfo => new SqlConnectionStringBuilder(_connectionString);
16 |
17 | protected virtual IDbConnection GetConnection() => new SqlConnection(_connectionString);
18 |
19 | ///
20 | /// Returns an opened connection
21 | ///
22 | ///
23 | public IDbConnection GetOpenedConnection()
24 | {
25 | var connection = GetConnection();
26 | connection.Open();
27 | return connection;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/DatabaseService.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using System;
3 | using UserManager.BusinessLogic.DataAccess.Repositories;
4 |
5 | namespace UserManager.BusinessLogic.DataAccess
6 | {
7 | public class DatabaseService : IDatabaseService
8 | {
9 | private readonly DatabaseContext _databaseContext;
10 | private readonly IDatabaseRepository _databaseRepository;
11 |
12 | public DatabaseService(DatabaseContext databaseContext, IDatabaseRepository databaseRepository)
13 | {
14 | _databaseContext = databaseContext;
15 | _databaseRepository = databaseRepository;
16 | }
17 |
18 | public string GetName() => _databaseContext.ConnectionInfo.InitialCatalog;
19 |
20 | public string GetServer() => _databaseContext.ConnectionInfo.DataSource;
21 |
22 | public async Task CanConnectToDatabase()
23 | {
24 | try
25 | {
26 | var databaseVersion = await _databaseRepository.GetDatabaseVersion();
27 | return true;
28 | }
29 | catch (Exception)
30 | {
31 | return false;
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/IDatabaseService.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace UserManager.BusinessLogic.DataAccess
4 | {
5 | public interface IDatabaseService
6 | {
7 | string GetName();
8 |
9 | Task CanConnectToDatabase();
10 | string GetServer();
11 | }
12 | }
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/Mappers/EmailMapper.cs:
--------------------------------------------------------------------------------
1 | using Dapper;
2 | using UserManager.BusinessLogic.Model;
3 |
4 | namespace UserManager.BusinessLogic.DataAccess.Mappers
5 | {
6 | public class EmailMapper : SqlMapper.StringTypeHandler
7 | {
8 | protected override string Format(Email email) => email.ToString();
9 |
10 | protected override Email Parse(string email) => new Email(email);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/Mappers/IntTypeHandler.cs:
--------------------------------------------------------------------------------
1 | using Dapper;
2 | using System;
3 | using System.Data;
4 |
5 | namespace UserManager.BusinessLogic.DataAccess.Mappers
6 | {
7 | ///
8 | /// Inspired by
9 | ///
10 | ///
11 | public abstract class IntTypeHandler : SqlMapper.TypeHandler
12 | {
13 | public override T Parse(object value)
14 | {
15 | if (value == null || value is DBNull) return default(T);
16 | return Parse(Convert.ToInt32(value));
17 | }
18 |
19 | public override void SetValue(IDbDataParameter parameter, T value)
20 | {
21 | parameter.Value = value == null ? (object) DBNull.Value : Format(value);
22 | }
23 |
24 | protected abstract int Format(T xml);
25 |
26 | protected abstract T Parse(int xml);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/Mappers/RoleMapper.cs:
--------------------------------------------------------------------------------
1 | using UserManager.BusinessLogic.Model;
2 |
3 | namespace UserManager.BusinessLogic.DataAccess.Mappers
4 | {
5 | public class RoleMapper : IntTypeHandler
6 | {
7 | protected override int Format(Role role) => role.Id;
8 |
9 | protected override Role Parse(int roleId) => Role.FromId(roleId);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/Repositories/DatabaseRepository.cs:
--------------------------------------------------------------------------------
1 | using Dapper;
2 | using System.Threading.Tasks;
3 |
4 | namespace UserManager.BusinessLogic.DataAccess.Repositories
5 | {
6 | public class DatabaseRepository : IDatabaseRepository
7 | {
8 | private readonly DatabaseContext _context;
9 |
10 | public DatabaseRepository(DatabaseContext context)
11 | {
12 | _context = context;
13 | }
14 |
15 | public async Task GetDatabaseVersion()
16 | {
17 | using (var connection = _context.GetOpenedConnection())
18 | {
19 | return await connection.QueryFirstAsync("SELECT @@version");
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/Repositories/IDatabaseRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace UserManager.BusinessLogic.DataAccess.Repositories
4 | {
5 | public interface IDatabaseRepository
6 | {
7 | Task GetDatabaseVersion();
8 | }
9 | }
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/Repositories/IRoleRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading.Tasks;
3 | using UserManager.BusinessLogic.Model;
4 |
5 | namespace UserManager.BusinessLogic.DataAccess.Repositories
6 | {
7 | public interface IRoleRepository
8 | {
9 | Task> GetAll();
10 | }
11 | }
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/Repositories/IUserRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading.Tasks;
3 | using UserManager.BusinessLogic.Model;
4 |
5 | namespace UserManager.BusinessLogic.DataAccess.Repositories
6 | {
7 | public interface IUserRepository
8 | {
9 | Task GetById(int id);
10 |
11 | Task> GetAll();
12 |
13 | Task CreateUser(User user);
14 |
15 | Task UpdateUser(User user);
16 |
17 | Task Remove(int id);
18 | }
19 | }
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/Repositories/RoleRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 | using UserManager.BusinessLogic.Model;
5 |
6 | namespace UserManager.BusinessLogic.DataAccess.Repositories
7 | {
8 | public class RoleRepository : IRoleRepository
9 | {
10 | public Task> GetAll() => Task.FromResult(Role.Roles.ToList());
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/DataAccess/Repositories/UserRepository.cs:
--------------------------------------------------------------------------------
1 | using Dapper;
2 | using Dapper.Contrib.Extensions;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 | using UserManager.BusinessLogic.Model;
6 |
7 | namespace UserManager.BusinessLogic.DataAccess.Repositories
8 | {
9 | public class UserRepository : IUserRepository
10 | {
11 | private readonly DatabaseContext _context;
12 |
13 | public UserRepository(DatabaseContext context)
14 | {
15 | _context = context;
16 | }
17 |
18 | public async Task CreateUser(User user)
19 | {
20 | using (var connection = _context.GetOpenedConnection())
21 | {
22 | return await connection.InsertAsync(user);
23 | }
24 | }
25 |
26 | public async Task> GetAll()
27 | {
28 | using (var connection = _context.GetOpenedConnection())
29 | {
30 | return await connection.GetAllAsync().ToListAsync();
31 | }
32 | }
33 |
34 | public async Task GetById(int id)
35 | {
36 | using (var connection = _context.GetOpenedConnection())
37 | {
38 | return await connection.GetAsync(id);
39 | }
40 | }
41 |
42 | public async Task UpdateUser(User user)
43 | {
44 | // Nothing, this is updated by reference
45 | }
46 |
47 | public async Task Remove(int id)
48 | {
49 | using (var connection = _context.GetOpenedConnection())
50 | {
51 | await connection.ExecuteAsync("DELETE FROM [User] WHERE Id = @Id", new { Id = id });
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/Exceptions/NotFoundException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace UserManager.BusinessLogic.Exceptions
4 | {
5 | public class NotFoundException : Exception
6 | {
7 | public NotFoundException(string message) : base(message)
8 | {
9 |
10 | }
11 |
12 | public NotFoundException(string type, string parameter, object id) : this($"{type} not found with {parameter} = {id}")
13 | {
14 |
15 | }
16 |
17 | public NotFoundException(string type, object id) : this(type, "id", id)
18 | {
19 |
20 | }
21 | }
22 |
23 | public class NotFoundException : NotFoundException
24 | {
25 | public NotFoundException(string message) : base(message)
26 | {
27 |
28 | }
29 |
30 | public NotFoundException(string parameter, object id) : base($"{typeof(T).Name} not found with {parameter} = {id}")
31 | {
32 |
33 | }
34 |
35 | public NotFoundException(object id) : base(typeof(T).Name, "id", id)
36 | {
37 |
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/Extensions/LogExtensions.cs:
--------------------------------------------------------------------------------
1 | using Serilog;
2 | using System;
3 |
4 | namespace UserManager.BusinessLogic.Extensions
5 | {
6 | public static class LogExtensions
7 | {
8 | public static void Error(this ILogger logger, Exception ex) => logger.Error(ex, "{ExceptionMessage}", ex.Message);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/Model/Email.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | using System.Text.RegularExpressions;
3 |
4 | namespace UserManager.BusinessLogic.Model
5 | {
6 | public class Email
7 | {
8 | private readonly string _email;
9 |
10 | public Email(string email)
11 | {
12 | new EmailValidator().Validate(email);
13 | _email = email;
14 | }
15 |
16 | public override string ToString() => _email;
17 | }
18 |
19 | public class EmailValidator
20 | {
21 | public void Validate(string email)
22 | {
23 | if (!IsValid(email))
24 | {
25 | throw new ValidationException($"Invalid Email: {email}");
26 | }
27 | }
28 |
29 | ///
30 | /// Validate email based on
31 | ///
32 | ///
33 | ///
34 | public bool IsValid(string email)
35 | {
36 | return new EmailAddressAttribute().IsValid(email);
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/Model/EmailAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 | using System.Text.RegularExpressions;
4 |
5 | namespace UserManager.BusinessLogic.Model
6 | {
7 |
8 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
9 | public class EmailAttribute : ValidationAttribute
10 | {
11 | private static readonly EmailValidator _validator = new EmailValidator();
12 |
13 | public override bool IsValid(object value)
14 | {
15 | if (value == null)
16 | {
17 | return true; // This should be handled by Required attribute
18 | }
19 |
20 | if(!(value is string))
21 | {
22 | throw new ArgumentException($"string type required. Found {value.GetType()}", nameof(value));
23 | }
24 |
25 | var email = value as string;
26 | return _validator.IsValid(email);
27 | }
28 |
29 | protected override ValidationResult IsValid(object value, ValidationContext validationContext)
30 | {
31 | var email = value as string;
32 | if(email != null)
33 | {
34 | var isValid = _validator.IsValid(email);
35 | if (!isValid)
36 | {
37 | return new ValidationResult($"Invalid Email: {email}");
38 | }
39 | }
40 |
41 | return base.IsValid(value, validationContext);
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/Model/Role.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace UserManager.BusinessLogic.Model
4 | {
5 | public class Role
6 | {
7 | private Role(int id, string name, string description)
8 | {
9 | Id = id;
10 | Name = name;
11 | Description = description;
12 | }
13 |
14 | public int Id { get; }
15 |
16 | public string Name { get; }
17 |
18 | public string Description { get; }
19 |
20 | public static Role Admin { get; } = new Role(1, "Admin", "Role which can perform elevated actions");
21 |
22 | public static Role Basic { get; } = new Role(2, "Basic", "Role which can only read info");
23 |
24 | public static Role[] Roles { get; } = new Role[] { Admin, Basic };
25 |
26 | public static Role FromId(int id)
27 | {
28 | if (id == Admin.Id) return Admin;
29 | if (id == Basic.Id) return Basic;
30 |
31 | throw new ArgumentException($"Invalid value {id}", nameof(id));
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/Model/User.cs:
--------------------------------------------------------------------------------
1 | using Dapper.Contrib.Extensions;
2 | using System;
3 |
4 | namespace UserManager.BusinessLogic.Model
5 | {
6 | [Table("[User]")]
7 | public class User
8 | {
9 | public User()
10 | {
11 | this.CreationDate = DateTimeOffset.Now;
12 | }
13 |
14 | [Key]
15 | public int Id { get; private set; }
16 |
17 | public string FirstName { get; set; }
18 |
19 | public string LastName { get; set; }
20 |
21 | public Email Email { get; set; }
22 |
23 | public Role Role { get; set; }
24 |
25 | public DateTimeOffset CreationDate { get; }
26 | }
27 | }
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UserManager.BusinessLogic")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UserManager.BusinessLogic")]
13 | [assembly: AssemblyCopyright("Copyright © 2020")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("ce9a2929-ed77-489b-b161-6c10fd8a5d3a")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/UserManager.BusinessLogic/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/UserManager.DataAccess.Migrations/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/UserManager.DataAccess.Migrations/Command.cs:
--------------------------------------------------------------------------------
1 | using Ardalis.SmartEnum;
2 | using FluentMigrator.Runner;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using System;
5 | using System.Linq;
6 |
7 | namespace UserManager.DataAccess.Migrations
8 | {
9 | public abstract class Command : SmartEnum
10 | {
11 | private Command(string name, int value) : base(name, value) { }
12 |
13 | public static readonly Command MigrateToLatest = new MigrateToLatestCommand();
14 | public static readonly Command Rollback = new RollbackCommand();
15 |
16 | public static (Command Command, string[] arguments) FromString(string text)
17 | {
18 | var commandParameters = text.Split(' ').ToList();
19 | var command = commandParameters[0];
20 | commandParameters.RemoveAt(0);
21 | return (FromName(command), commandParameters.ToArray());
22 | }
23 |
24 | public string Arguments { get; }
25 |
26 | public abstract void Execute(IServiceProvider serviceProvider, string[] arguments);
27 |
28 | private sealed class MigrateToLatestCommand : Command
29 | {
30 | public MigrateToLatestCommand() : base("MigrateToLatest", 1) { }
31 |
32 | public override void Execute(IServiceProvider serviceProvider, string[] arguments)
33 | {
34 | // Instantiate the runner
35 | var runner = serviceProvider.GetRequiredService();
36 |
37 | // Execute the migrations
38 | runner.MigrateUp();
39 | }
40 | }
41 |
42 | private class RollbackCommand : Command
43 | {
44 | public RollbackCommand() : base("Rollback", 2) { }
45 |
46 | public override void Execute(IServiceProvider serviceProvider, string[] arguments)
47 | {
48 | // Instantiate the runner
49 | var runner = serviceProvider.GetRequiredService();
50 |
51 | // Migrate down to version
52 | var version = long.Parse(arguments[0]);
53 | runner.MigrateDown(version);
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/UserManager.DataAccess.Migrations/FluentMigratorExtensions.cs:
--------------------------------------------------------------------------------
1 | using FluentMigrator.Builders.Create.Table;
2 |
3 | namespace UserManager.DataAccess.Migrations
4 | {
5 | public static class FluentMigratorExtensions
6 | {
7 | public static ICreateTableColumnOptionOrWithColumnSyntax WithIdColumn(this ICreateTableWithColumnSyntax tableWithColumnSyntax)
8 | {
9 | return tableWithColumnSyntax
10 | .WithColumn("Id")
11 | .AsInt32()
12 | .NotNullable()
13 | .PrimaryKey()
14 | .Identity();
15 | }
16 |
17 | public static ICreateTableColumnOptionOrWithColumnSyntax WithTimeStamps(this ICreateTableWithColumnSyntax tableWithColumnSyntax)
18 | {
19 | return tableWithColumnSyntax
20 | .WithColumn("CreatedAt").AsDateTime().NotNullable()
21 | .WithColumn("ModifiedAt").AsDateTime().NotNullable();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/UserManager.DataAccess.Migrations/Migrations/20201024202704_InitialMigration.cs:
--------------------------------------------------------------------------------
1 | using FluentMigrator;
2 |
3 | namespace UserManager.DataAccess.Migrations.Migrations
4 | {
5 | [Migration(20201024202704)]
6 | public class InitialMigration : Migration
7 | {
8 | public override void Up()
9 | {
10 |
11 | }
12 |
13 | public override void Down()
14 | {
15 |
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/UserManager.DataAccess.Migrations/Migrations/20201024202825_AddUserTable.cs:
--------------------------------------------------------------------------------
1 | using FluentMigrator;
2 |
3 | namespace UserManager.DataAccess.Migrations.Migrations
4 | {
5 | [Migration(20201024202825)]
6 | public class AddUserTable : Migration
7 | {
8 | public override void Up()
9 | {
10 | Create.Table("User")
11 | .WithIdColumn()
12 | .WithColumn("FirstName").AsString(50).NotNullable()
13 | .WithColumn("LastName").AsString(100).NotNullable()
14 | .WithColumn("Email").AsString(50).NotNullable();
15 | }
16 |
17 | public override void Down()
18 | {
19 | Delete.Table("User");
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/UserManager.DataAccess.Migrations/Migrations/20201113194828_AddRoleToUser.cs:
--------------------------------------------------------------------------------
1 | using FluentMigrator;
2 | using UserManager.BusinessLogic.Model;
3 |
4 | namespace UserManager.DataAccess.Migrations.Migrations
5 | {
6 | [Migration(20201113194828)]
7 | public class AddRoleToUser : Migration
8 | {
9 | public override void Up()
10 | {
11 | Alter.Table("User")
12 | .AddColumn("Role").AsInt16().WithDefaultValue(Role.Basic.Id);
13 | }
14 |
15 | public override void Down()
16 | {
17 | Delete.Column("Role")
18 | .FromTable("User");
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/UserManager.DataAccess.Migrations/Migrations/20210114223404_AddCreationDateToUser.cs:
--------------------------------------------------------------------------------
1 | using FluentMigrator;
2 |
3 | namespace UserManager.DataAccess.Migrations.Migrations
4 | {
5 | [Migration(20210114223404)]
6 | public class AddCreationDateToUser : Migration
7 | {
8 | public override void Up()
9 | {
10 | Alter.Table("User")
11 | .AddColumn("CreationDate").AsDateTimeOffset().Nullable();
12 |
13 | Update.Table("User").Set(new { CreationDate = RawSql.Insert("SYSDATETIMEOFFSET()") }).AllRows();
14 |
15 | Alter.Table("User")
16 | .AlterColumn("CreationDate").AsDateTimeOffset().NotNullable();
17 | }
18 |
19 | public override void Down()
20 | {
21 | Delete.Column("CreationDate")
22 | .FromTable("User");
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/UserManager.DataAccess.Migrations/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UserManager.DataAccess.Migrations")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UserManager.DataAccess.Migrations")]
13 | [assembly: AssemblyCopyright("Copyright © 2020")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("2cb3fa12-fa7c-4a07-8475-8f7ccec282d2")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/UserManager.IntegrationTests/Main/MainMenuTests.cs:
--------------------------------------------------------------------------------
1 | using FlaUI.Core.AutomationElements;
2 | using FluentAssertions;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 | using WinformsTools.IntegrationTestUtils.Extensions;
5 | using WinformsTools.IntegrationTestUtils.Elements;
6 | using UserManager.IntegrationTests.TestUtils;
7 | using UserManager.Resources;
8 |
9 | namespace UserManager.IntegrationTests.Main
10 | {
11 | [TestClass]
12 | public class MainMenuTests : TestBase
13 | {
14 | [TestMethod]
15 | public void MainView_only_allows_to_open_one_windows_type_at_the_same_time()
16 | {
17 | var mainWindow = App.GetMainWindow();
18 | var gotoUsersButton = mainWindow.Get