Added FxCop and get Organization Unit selection running

This commit is contained in:
Holger Börchers 2020-08-13 22:53:44 +02:00
parent fc5c6d0ce7
commit 23da5583fd
17 changed files with 84 additions and 47 deletions

4
.editorconfig Normal file
View File

@ -0,0 +1,4 @@
[*.cs]
# CA1822: Member als statisch markieren
dotnet_diagnostic.CA1822.severity = suggestion

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore; using System;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic; using System.Collections.Generic;
namespace UserService.DatabaseLayer.DataModels namespace UserService.DatabaseLayer.DataModels
@ -7,6 +8,7 @@ namespace UserService.DatabaseLayer.DataModels
{ {
public static void Seed(this ModelBuilder modelBuilder) public static void Seed(this ModelBuilder modelBuilder)
{ {
if (modelBuilder == null) throw new ArgumentNullException(nameof(modelBuilder));
var groups = new OrganizationUnit { CommonName = "Groups", Id = -1 }; var groups = new OrganizationUnit { CommonName = "Groups", Id = -1 };
var users = new OrganizationUnit { CommonName = "Users", Id = -2 }; var users = new OrganizationUnit { CommonName = "Users", Id = -2 };
var germany = new OrganizationUnit{CommonName = "Germany", Id = -6, ParentId = -2}; var germany = new OrganizationUnit{CommonName = "Germany", Id = -6, ParentId = -2};
@ -25,6 +27,7 @@ namespace UserService.DatabaseLayer.DataModels
public static void CreateRelations(this ModelBuilder modelBuilder) public static void CreateRelations(this ModelBuilder modelBuilder)
{ {
if (modelBuilder == null) throw new ArgumentNullException(nameof(modelBuilder));
modelBuilder.Entity<UserMember>() modelBuilder.Entity<UserMember>()
.HasKey(bc => new { bc.MemberId, bc.UserId }); .HasKey(bc => new { bc.MemberId, bc.UserId });
modelBuilder.Entity<UserMember>() modelBuilder.Entity<UserMember>()
@ -47,6 +50,7 @@ namespace UserService.DatabaseLayer.DataModels
{ {
public static IEnumerable<SecurityGroup> GetSecurityGroups(this User user) public static IEnumerable<SecurityGroup> GetSecurityGroups(this User user)
{ {
if (user == null) throw new ArgumentNullException(nameof(user));
foreach (var userMember in user.MemberOf) foreach (var userMember in user.MemberOf)
{ {
if (userMember.Member is SecurityGroup securityGroup) if (userMember.Member is SecurityGroup securityGroup)
@ -62,6 +66,7 @@ namespace UserService.DatabaseLayer.DataModels
{ {
public static IEnumerable<User> GetUsers(this SecurityGroup securityGroup) public static IEnumerable<User> GetUsers(this SecurityGroup securityGroup)
{ {
if (securityGroup == null) throw new ArgumentNullException(nameof(securityGroup));
foreach (var userMember in securityGroup.Members) foreach (var userMember in securityGroup.Members)
{ {
if (userMember.User is null) continue; if (userMember.User is null) continue;

View File

@ -1,7 +1,7 @@
using System; #nullable enable
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Text;
namespace UserService.DatabaseLayer.DataModels namespace UserService.DatabaseLayer.DataModels
{ {

View File

@ -12,7 +12,7 @@ namespace UserService.DatabaseLayer.Repository
{ {
public class BaseRepository<T> where T : Node public class BaseRepository<T> where T : Node
{ {
protected readonly Func<UserServiceDbContext, DbSet<T>> Context; protected Func<UserServiceDbContext, DbSet<T>> Context { get; }
protected BaseRepository(Func<UserServiceDbContext, DbSet<T>> context) protected BaseRepository(Func<UserServiceDbContext, DbSet<T>> context)
{ {
@ -22,27 +22,27 @@ namespace UserService.DatabaseLayer.Repository
public virtual async Task<IReadOnlyList<T>> GetAllAsync(Expression<Func<T, bool>>? predicate = null, CancellationToken token = default) public virtual async Task<IReadOnlyList<T>> GetAllAsync(Expression<Func<T, bool>>? predicate = null, CancellationToken token = default)
{ {
await using var db = new UserServiceDbContext(); await using var db = new UserServiceDbContext();
return await Context(db).Include(x => x.Parent).WhereOrDefault(predicate).ToListAsync(token); return await Context(db).Include(x => x.Parent).WhereOrDefault(predicate).ToListAsync(token).ConfigureAwait(false);
} }
public async Task<T?> GetAsync(Expression<Func<T, bool>> predicate, CancellationToken token = default) public async Task<T?> GetAsync(Expression<Func<T, bool>> predicate, CancellationToken token = default)
{ {
await using var db = new UserServiceDbContext(); await using var db = new UserServiceDbContext();
return await Context(db).FirstOrDefaultAsync(predicate, token); return await Context(db).FirstOrDefaultAsync(predicate, token).ConfigureAwait(false);
} }
public async Task AddAsync(T entity, CancellationToken token = default) public async Task AddAsync(T entity, CancellationToken token = default)
{ {
await using var db = new UserServiceDbContext(); await using var db = new UserServiceDbContext();
await Context(db).AddAsync(@entity, token); await Context(db).AddAsync(@entity, token).ConfigureAwait(false);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token).ConfigureAwait(false);
} }
public async Task<bool> UpdateAsync(T entity, CancellationToken token = default) public async Task<bool> UpdateAsync(T entity, CancellationToken token = default)
{ {
await using var db = new UserServiceDbContext(); await using var db = new UserServiceDbContext();
Context(db).Update(entity); Context(db).Update(entity);
var items= await db.SaveChangesAsync(token); var items= await db.SaveChangesAsync(token).ConfigureAwait(false);
return items > 0; return items > 0;
} }
@ -50,7 +50,7 @@ namespace UserService.DatabaseLayer.Repository
{ {
await using var db = new UserServiceDbContext(); await using var db = new UserServiceDbContext();
Context(db).Remove(entity); Context(db).Remove(entity);
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token).ConfigureAwait(false);
} }
} }
} }

View File

@ -24,7 +24,7 @@ namespace UserService.DatabaseLayer.Repository
var rootOus = await Context(db) var rootOus = await Context(db)
.Include(x => x.Parent) .Include(x => x.Parent)
.WhereOrDefault(predicate) .WhereOrDefault(predicate)
.ToListAsync(cancellationToken: token); .ToListAsync(cancellationToken: token).ConfigureAwait(false);
IEnumerable<OrganizationUnit> Rec(Node node) IEnumerable<OrganizationUnit> Rec(Node node)
{ {

View File

@ -7,11 +7,15 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.6"> <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.7" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -19,10 +19,10 @@ namespace UserService.Test
public async Task Test1() public async Task Test1()
{ {
await using var db = new UserServiceDbContext(); await using var db = new UserServiceDbContext();
var user = await db.Users.FirstOrDefaultAsync(); var user = await db.Users.FirstOrDefaultAsync().ConfigureAwait(false);
var secGroup = await db.SecurityGroups.FirstOrDefaultAsync(); var secGroup = await db.SecurityGroups.FirstOrDefaultAsync().ConfigureAwait(false);
var ous = await db.OrganizationUnits.ToListAsync(); var ous = await db.OrganizationUnits.ToListAsync().ConfigureAwait(false);
var mo = await db.UserMembers.ToListAsync(); var mo = await db.UserMembers.ToListAsync().ConfigureAwait(false);
var securityGroupsOfUser = user.GetSecurityGroups(); var securityGroupsOfUser = user.GetSecurityGroups();
var usersOfSecurityGroup = secGroup.GetUsers(); var usersOfSecurityGroup = secGroup.GetUsers();
@ -38,7 +38,7 @@ namespace UserService.Test
public async Task Test2() public async Task Test2()
{ {
await using var db = new UserServiceDbContext(); await using var db = new UserServiceDbContext();
var ous = await db.OrganizationUnits.ToListAsync(); var ous = await db.OrganizationUnits.ToListAsync().ConfigureAwait(false);
var sb = new StringBuilder(); var sb = new StringBuilder();
NewMethod(ous, null, 0, ref sb); NewMethod(ous, null, 0, ref sb);
var result = sb.ToString(); var result = sb.ToString();

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
@ -7,9 +7,13 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="nunit" Version="3.12.0" /> <PackageReference Include="nunit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

Binary file not shown.

View File

@ -9,6 +9,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserService.Test", "UserSer
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserService.DatabaseLayer", "UserService.DatabaseLayer\UserService.DatabaseLayer.csproj", "{4505C991-7E39-416F-94E5-D906DD0D90F9}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserService.DatabaseLayer", "UserService.DatabaseLayer\UserService.DatabaseLayer.csproj", "{4505C991-7E39-416F-94E5-D906DD0D90F9}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A8D411B0-CD71-4448-9D4F-12898D0CCDD6}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU

View File

@ -1,5 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
@ -27,14 +26,14 @@ namespace UserService.Pages
private async void OnSelectedNodeChanged(Node? value) private async void OnSelectedNodeChanged(Node? value)
{ {
if (value == null) return; if (value == null) return;
Members = await UsersRepository.GetAllAsync(x => x.ParentId == value.Id); Members = await UsersRepository.GetAllAsync(x => x.ParentId == value.Id).ConfigureAwait(false);
} }
public IReadOnlyList<Member> Members { get; set; } public IReadOnlyList<Member>? Members { get; set; }
[Inject] public IOrganizationUnitsRepository OuRepository { get; set; } [Inject] public IOrganizationUnitsRepository OuRepository { get; set; } = null!;
[Inject] public IUsersRepository UsersRepository { get; set; } [Inject] public IUsersRepository UsersRepository { get; set; } = null!;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()

View File

@ -4,7 +4,7 @@
<h1>Table of all security groups</h1> <h1>Table of all security groups</h1>
@if (SecurityGroups is null) @if (Groups is null)
{ {
<p> <p>
<em>Loading...</em> <em>Loading...</em>
@ -12,7 +12,7 @@
} }
else else
{ {
<DataGrid TItem="SecurityGroup" Data="@SecurityGroups"> <DataGrid TItem="SecurityGroup" Data="@Groups">
<DataGridCommandColumn TItem="User" /> <DataGridCommandColumn TItem="User" />
<DataGridColumn TItem="SecurityGroup" Field="@nameof(SecurityGroup.Id)" Caption="#" Sortable="false" /> <DataGridColumn TItem="SecurityGroup" Field="@nameof(SecurityGroup.Id)" Caption="#" Sortable="false" />
<DataGridColumn TItem="SecurityGroup" Field="@nameof(SecurityGroup.CommonName)" Caption="CN" Editable="true" /> <DataGridColumn TItem="SecurityGroup" Field="@nameof(SecurityGroup.CommonName)" Caption="CN" Editable="true" />

View File

@ -8,18 +8,18 @@ namespace UserService.Pages
{ {
public class SecurityGroupsBase : ComponentBase public class SecurityGroupsBase : ComponentBase
{ {
[Inject] private ISecurityGroupsRepository? SecurityGroupsRepository { get; set; } [Inject] private ISecurityGroupsRepository SecurityGroupsRepository { get; set; } = null!;
[Inject] private IOrganizationUnitsRepository? OrganizationUnitsRepository { get; set; } [Inject] private IOrganizationUnitsRepository OrganizationUnitsRepository { get; set; } = null!;
protected bool DialogIsOpen; protected bool DialogIsOpen { get; set; }
protected SecurityGroup? SecurityGroupToEdit; protected SecurityGroup? SecurityGroupToEdit { get; set; }
protected IReadOnlyList<SecurityGroup>? SecurityGroups; protected IReadOnlyList<SecurityGroup>? Groups { get; set; }
protected IReadOnlyList<OrganizationUnit>? OrganizationUnits; protected IReadOnlyList<OrganizationUnit>? OrganizationUnits { get; set; }
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
SecurityGroups = await SecurityGroupsRepository.GetAllAsync().ConfigureAwait(false); Groups = await SecurityGroupsRepository.GetAllAsync().ConfigureAwait(false);
OrganizationUnits = await OrganizationUnitsRepository.GetAllAsync().ConfigureAwait(false); OrganizationUnits = await OrganizationUnitsRepository.GetAllAsync().ConfigureAwait(false);
} }

View File

@ -29,24 +29,23 @@ else
<DataGridColumn TItem="User" Field="@nameof(User.FirstName)" Caption="First Name" Editable="true"/> <DataGridColumn TItem="User" Field="@nameof(User.FirstName)" Caption="First Name" Editable="true"/>
<DataGridColumn TItem="User" Field="@nameof(User.LastName)" Caption="Last Name" Editable="true"/> <DataGridColumn TItem="User" Field="@nameof(User.LastName)" Caption="Last Name" Editable="true"/>
<DataGridColumn TItem="User" Field="@nameof(User.EMail)" Caption="EMail" Editable="true"/> <DataGridColumn TItem="User" Field="@nameof(User.EMail)" Caption="EMail" Editable="true"/>
<DataGridSelectColumn TItem="User" Field="@nameof(User.Parent)" Caption="Parent" Editable="true"> <DataGridSelectColumn TItem="User" Field="@nameof(User.ParentId)" Caption="Parent" Editable="true">
<DisplayTemplate> <DisplayTemplate>
@{ @{
var name = ((User) context).Parent?.CommonName ?? "-"; var name = ((User) context ).Parent?.CommonName ?? "-";
@name @name
} }
</DisplayTemplate> </DisplayTemplate>
<EditTemplate> <EditTemplate>
@{
<Blazorise.SelectEdit TValue="User" SelectedValue="@((User)(context.CellValue))" SelectedValueChanged="@(v => context.CellValue = v)"> <Select TValue="int" SelectedValue="@((int)(context.CellValue))" SelectedValueChanged="@(v => context.CellValue = v)" >
@foreach (var item in OrganizationUnits) @foreach (var item in OrganizationUnits)
{ {
<SelectItem TValue="int" Value="@(item.Id)">@item.CommonName</SelectItem>
<SelectItem TValue="OrganizationUnit" Value="@(item)">@item.CommonName</SelectItem>
} }
</Blazorise.SelectEdit> </Select>
}
</EditTemplate> </EditTemplate>
</DataGridSelectColumn> </DataGridSelectColumn>

View File

@ -1,5 +1,7 @@
using Microsoft.AspNetCore.Components; using System;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Blazorise.DataGrid; using Blazorise.DataGrid;
using Microsoft.JSInterop; using Microsoft.JSInterop;
@ -20,19 +22,21 @@ namespace UserService.Pages
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
Users = await UsersRepository.GetAllAsync(); Users = await UsersRepository.GetAllAsync().ConfigureAwait(false);
OrganizationUnits = await OrganizationUnitsRepository.GetAllAsync().ConfigureAwait(false); OrganizationUnits = await OrganizationUnitsRepository.GetAllAsync().ConfigureAwait(false);
} }
protected async Task RowInsertedCallback(SavedRowItem<User, Dictionary<string, object>> arg) protected async Task RowInsertedCallback(SavedRowItem<User, Dictionary<string, object>> arg)
{ {
if (arg == null) throw new ArgumentNullException(nameof(arg));
var user = arg.Item; var user = arg.Item;
user.ParentId = -2; user.ParentId = -2;
await UsersRepository.AddAsync(user); await UsersRepository.AddAsync(user).ConfigureAwait(false);
} }
protected async Task RowDeletingCallback(CancellableRowChange<User> arg) protected async Task RowDeletingCallback(CancellableRowChange<User> arg)
{ {
if (arg == null) throw new ArgumentNullException(nameof(arg));
var confirmed = await JsRuntime.InvokeAsync<bool>("confirm", var confirmed = await JsRuntime.InvokeAsync<bool>("confirm",
$"You are about to delete the user {arg.Item.FullName}. Are you sure?").ConfigureAwait(false); $"You are about to delete the user {arg.Item.FullName}. Are you sure?").ConfigureAwait(false);
if (confirmed) if (confirmed)
@ -46,7 +50,10 @@ namespace UserService.Pages
protected async Task RowUpdatingCallback(CancellableRowChange<User, Dictionary<string, object>> arg) protected async Task RowUpdatingCallback(CancellableRowChange<User, Dictionary<string, object>> arg)
{ {
var result = await UsersRepository.UpdateAsync(arg.Item); if (arg == null) throw new ArgumentNullException(nameof(arg));
var user = arg.Item;
user.Parent = OrganizationUnits.FirstOrDefault(x => x.Id == (int?)arg.Values[nameof(Node.ParentId)]);
var result = await UsersRepository.UpdateAsync(user).ConfigureAwait(false);
arg.Cancel = !result; arg.Cancel = !result;
} }

View File

@ -1,3 +1,4 @@
using System;
using Blazorise; using Blazorise;
using Blazorise.Bootstrap; using Blazorise.Bootstrap;
using Blazorise.Icons.FontAwesome; using Blazorise.Icons.FontAwesome;
@ -40,6 +41,7 @@ namespace UserService
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ {
if (app == null) throw new ArgumentNullException(nameof(app));
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();

View File

@ -5,6 +5,10 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\UserService.DatabaseLayer\UserService.DatabaseLayer.csproj" /> <ProjectReference Include="..\UserService.DatabaseLayer\UserService.DatabaseLayer.csproj" />
</ItemGroup> </ItemGroup>
@ -15,6 +19,10 @@
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="0.9.1.2" /> <PackageReference Include="Blazorise.Icons.FontAwesome" Version="0.9.1.2" />
<PackageReference Include="Blazorise.Sidebar" Version="0.9.1.2" /> <PackageReference Include="Blazorise.Sidebar" Version="0.9.1.2" />
<PackageReference Include="Blazorise.TreeView" Version="0.9.1.2" /> <PackageReference Include="Blazorise.TreeView" Version="0.9.1.2" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup> </ItemGroup>
</Project> </Project>