Skip to content

Commit 0297762

Browse files
committed
added AccountService and removed EF dependency in OpentIddict-UI Identity Api project
1 parent ecd1b8c commit 0297762

20 files changed

+317
-134
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ services.AddOpenIddict()
123123
}
124124
})
125125
// Register the EF based UI Store for the ASP.NET Identity related entities.
126-
.AddUIIdentityStore(options =>
126+
.AddUIIdentityStore<ApplicationUser>(options =>
127127
{
128128
options.OpenIddictUIIdentityContext = builder =>
129129
builder.UseSqlite(Configuration.GetConnectionString("DefaultConnection"),

notes.txt

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
TODO:
22

3-
- go full razor pages
4-
- https://github.com/openiddict/openiddict-samples/tree/dev/samples/Contruum/Contruum.Server
5-
6-
7-
- migrate to .net Program.cs file
8-
- refactor DB-migrations in sample server
9-
10-
11-
- load options.Permissions from database instead of configuring it
3+
- for next release 1.5.0
4+
- mention small API change when registering .AddUIIdentityStore<ApplicationUser> the TApplicationUser is not mandatory!
125

136

147
- client refactoring
@@ -18,6 +11,13 @@ TODO:
1811
- check server stylings not removed
1912

2013

14+
- load options.Permissions from database instead of configuring it
15+
16+
17+
- go full razor pages
18+
- https://github.com/openiddict/openiddict-samples/tree/dev/samples/Contruum/Contruum.Server
19+
20+
2121
- organize APIs a bit more by feature
2222
- i.e. identity -> AccountController
2323
- AccountController

samples/Server/ConfigureServices.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ string environmentName
172172
};
173173
})
174174
// Register the EF based UI Store for the ASP.NET Identity related entities.
175-
.AddUIIdentityStore(options =>
175+
.AddUIIdentityStore<ApplicationUser>(options =>
176176
{
177177
options.OpenIddictUIIdentityContext = builder =>
178178
builder.UseSqlite(configuration.GetConnectionString("DefaultConnection"),
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
using Microsoft.AspNetCore.Identity;
2-
using Microsoft.EntityFrameworkCore;
32
using System;
43
using System.Collections.Generic;
54
using System.Linq;
6-
using System.Security.Claims;
75
using System.Threading.Tasks;
86

7+
using tomware.OpenIddict.UI.Identity.Core;
8+
using tomware.OpenIddict.UI.Suite.Core;
9+
910
namespace tomware.OpenIddict.UI.Identity.Api
1011
{
1112
public interface IAccountApiService
@@ -21,50 +22,36 @@ public interface IAccountApiService
2122
public class AccountApiService<TIdentityUser> : IAccountApiService
2223
where TIdentityUser : IdentityUser, new()
2324
{
24-
// TODO: move UserManager down to Infrastructure
25-
// using Microsoft.EntityFrameworkCore is wrong in the Api layer!
26-
// remove package dependency <PackageReference Include="OpenIddict.EntityFrameworkCore" Version="3.0.5" />
27-
private readonly UserManager<TIdentityUser> _manager;
28-
private readonly IUserCreationStrategy<TIdentityUser> _userCreationStrategy;
25+
private readonly IAccountService _accountService;
2926

3027
public AccountApiService(
31-
UserManager<TIdentityUser> manager,
32-
IUserCreationStrategy<TIdentityUser> userCreationStrategy
28+
IAccountService accountService
3329
)
3430
{
35-
_manager = manager
36-
?? throw new ArgumentNullException(nameof(manager));
37-
_userCreationStrategy = userCreationStrategy
38-
?? throw new ArgumentNullException(nameof(userCreationStrategy));
31+
_accountService = accountService
32+
?? throw new ArgumentNullException(nameof(accountService));
3933
}
4034

4135
public async Task<IdentityResult> RegisterAsync(
4236
RegisterUserViewModel model
4337
)
4438
{
45-
var identiyUser = _userCreationStrategy.CreateUser(model);
39+
var param = SimpleMapper.From<RegisterUserViewModel, RegisterUserParam>(model);
4640

47-
return await _manager.CreateAsync(identiyUser, model.Password);
41+
return await _accountService.RegisterAsync(param);
4842
}
4943

5044
public async Task<IdentityResult> ChangePasswordAsync(ChangePasswordViewModel model)
5145
{
52-
var user = await _manager.FindByNameAsync(model.UserName);
46+
var param = SimpleMapper.From<ChangePasswordViewModel, ChangePasswordParam>(model);
5347

54-
return await _manager.ChangePasswordAsync(
55-
user,
56-
model.CurrentPassword,
57-
model.NewPassword
58-
);
48+
return await _accountService.ChangePasswordAsync(param);
5949
}
6050

6151
public async Task<IEnumerable<UserViewModel>> GetUsersAsync()
6252
{
6353
// TODO: Paging ???
64-
var items = await _manager.Users
65-
.OrderBy(u => u.UserName)
66-
.AsNoTracking()
67-
.ToListAsync();
54+
var items = await _accountService.GetUsersAsync();
6855

6956
return items.Select(u => new UserViewModel
7057
{
@@ -77,25 +64,21 @@ public async Task<IEnumerable<UserViewModel>> GetUsersAsync()
7764

7865
public async Task<UserViewModel> GetUserAsync(string id)
7966
{
80-
var user = await _manager.FindByIdAsync(id);
81-
var roles = await _manager.GetRolesAsync(user);
82-
var claims = await _manager.GetClaimsAsync(user);
83-
84-
var isLockedOut = await _manager.IsLockedOutAsync(user);
67+
var user = await _accountService.GetUserAsync(id);
8568

8669
return new UserViewModel
8770
{
8871
Id = user.Id,
8972
UserName = user.UserName,
9073
Email = user.Email,
9174
LockoutEnabled = user.LockoutEnabled,
92-
IsLockedOut = isLockedOut,
93-
Claims = new List<ClaimViewModel>(claims.ToList().Select(x => new ClaimViewModel
75+
IsLockedOut = user.IsLockedOut,
76+
Claims = new List<ClaimViewModel>(user.Claims.Select(x => new ClaimViewModel
9477
{
9578
Type = x.Type,
9679
Value = x.Value
9780
})),
98-
Roles = roles.ToList()
81+
Roles = user.Roles
9982
};
10083
}
10184

@@ -105,74 +88,21 @@ public async Task<IdentityResult> UpdateAsync(UserViewModel model)
10588
if (string.IsNullOrWhiteSpace(model.Id))
10689
throw new InvalidOperationException(nameof(model.Id));
10790

108-
var user = await _manager.FindByIdAsync(model.Id);
109-
user.UserName = model.UserName;
110-
user.Email = model.Email;
111-
user.LockoutEnabled = model.LockoutEnabled;
112-
113-
var result = await _manager.UpdateAsync(user);
114-
if (!result.Succeeded)
115-
{
116-
return result;
117-
}
118-
119-
result = await AssignClaimsAsync(
120-
user,
121-
model.Claims.Select(x => new Claim(x.Type, x.Value)).ToList()
122-
);
123-
if (!result.Succeeded)
124-
{
125-
return result;
126-
}
127-
128-
result = await AssignRolesAsync(user, model.Roles);
129-
if (!result.Succeeded)
91+
var param = SimpleMapper.From<UserViewModel, UserParam>(model);
92+
param.Claims = new List<ClaimInfo>(model.Claims.Select(c => new ClaimInfo
13093
{
131-
return result;
132-
}
94+
Type = c.Type,
95+
Value = c.Value
96+
}));
13397

134-
return result;
98+
return await _accountService.UpdateAsync(param);
13599
}
136100

137101
public async Task<IdentityResult> DeleteAsync(string id)
138102
{
139103
if (string.IsNullOrWhiteSpace(id)) throw new InvalidOperationException(nameof(id));
140104

141-
var user = await _manager.FindByIdAsync(id);
142-
143-
return await _manager.DeleteAsync(user);
144-
}
145-
146-
private async Task<IdentityResult> AssignClaimsAsync(
147-
TIdentityUser user,
148-
IEnumerable<Claim> claims
149-
)
150-
{
151-
// removing all claims
152-
var existingClaims = await _manager.GetClaimsAsync(user);
153-
await _manager.RemoveClaimsAsync(user, existingClaims);
154-
155-
// assigning claims
156-
return await _manager.AddClaimsAsync(
157-
user,
158-
claims
159-
);
160-
}
161-
162-
private async Task<IdentityResult> AssignRolesAsync(
163-
TIdentityUser user,
164-
IEnumerable<string> roles
165-
)
166-
{
167-
// removing all roles
168-
var existingRoles = await _manager.GetRolesAsync(user);
169-
await _manager.RemoveFromRolesAsync(user, existingRoles);
170-
171-
// assigning roles
172-
return await _manager.AddToRolesAsync(
173-
user,
174-
roles
175-
);
105+
return await _accountService.DeleteAsync(id);
176106
}
177107
}
178108
}

src/identity/OpenIddict.UI.Identity.Api/DependencyInjection.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.Extensions.DependencyInjection;
66
using Microsoft.AspNetCore.Authorization;
77
using tomware.OpenIddict.UI.Suite.Api;
8+
using tomware.OpenIddict.UI.Identity.Core;
89

910
namespace tomware.OpenIddict.UI.Identity.Api
1011
{
@@ -35,7 +36,7 @@ this OpenIddictBuilder builder
3536
) where TApplicationUser : IdentityUser, new()
3637
{
3738
builder.Services
38-
.AddTransient<IUserCreationStrategy<TApplicationUser>, UserNameUserCreationStrategy<TApplicationUser>>();
39+
.AddUserNameUserCreationStrategy<TApplicationUser>();
3940

4041
return builder;
4142
}
@@ -44,9 +45,8 @@ private static IServiceCollection AddApiServices<TApplicationUser>(
4445
this IServiceCollection services
4546
) where TApplicationUser : IdentityUser, new()
4647
{
47-
services.AddTransient<IUserCreationStrategy<TApplicationUser>, EmailUserCreationStrategy<TApplicationUser>>();
4848
services.AddTransient<IAccountApiService, AccountApiService<TApplicationUser>>();
49-
services.AddTransient<IRoleService, RoleService>();
49+
services.AddTransient<IRoleApiService, RoleApiService>();
5050
services.AddTransient<IClaimTypeApiService, ClaimTypeApiService>();
5151

5252
return services;

src/identity/OpenIddict.UI.Identity.Api/Role/RoleService.cs renamed to src/identity/OpenIddict.UI.Identity.Api/Role/RoleApiService.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace tomware.OpenIddict.UI.Identity.Api
88
{
9-
public interface IRoleService
9+
public interface IRoleApiService
1010
{
1111
Task<IEnumerable<RoleViewModel>> GetRolesAsync();
1212

@@ -19,11 +19,11 @@ public interface IRoleService
1919
Task DeleteAsync(string id);
2020
}
2121

22-
public class RoleService : IRoleService
22+
public class RoleApiService : IRoleApiService
2323
{
2424
private readonly RoleManager<IdentityRole> _manager;
2525

26-
public RoleService(RoleManager<IdentityRole> manager)
26+
public RoleApiService(RoleManager<IdentityRole> manager)
2727
{
2828
_manager = manager;
2929
}

src/identity/OpenIddict.UI.Identity.Api/Role/RoleController.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ namespace tomware.OpenIddict.UI.Identity.Api
88
[Route("roles")]
99
public class RoleController : IdentityApiController
1010
{
11-
private readonly IRoleService _service;
11+
private readonly IRoleApiService _service;
1212

13-
public RoleController(IRoleService service)
13+
public RoleController(IRoleApiService service)
1414
{
1515
_service = service;
1616
}

src/identity/OpenIddict.UI.Identity.Api/tomware.OpenIddict.UI.Identity.Api.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
2020
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="6.0.1" />
2121
<PackageReference Include="OpenIddict.AspNetCore" Version="3.1.1" />
22-
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="3.1.1" />
2322
</ItemGroup>
2423

2524
<ItemGroup>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace tomware.OpenIddict.UI.Identity.Core
2+
{
3+
public class ChangePasswordParam
4+
{
5+
public string CurrentPassword { get; set; }
6+
public string NewPassword { get; set; }
7+
public string UserName { get; set; }
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace tomware.OpenIddict.UI.Identity.Core
2+
{
3+
public class RegisterUserParam
4+
{
5+
public string UserName { get; set; }
6+
public string Email { get; set; }
7+
public string Password { get; set; }
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections.Generic;
2+
3+
namespace tomware.OpenIddict.UI.Identity.Core
4+
{
5+
public class ClaimInfo
6+
{
7+
public string Type { get; set; }
8+
public string Value { get; set; }
9+
}
10+
11+
public class UserInfo
12+
{
13+
public string Id { get; set; }
14+
15+
public string UserName { get; set; }
16+
17+
public string Email { get; set; }
18+
19+
public bool LockoutEnabled { get; set; }
20+
21+
public bool IsLockedOut { get; set; }
22+
23+
public List<ClaimInfo> Claims { get; set; } = new List<ClaimInfo>();
24+
25+
public List<string> Roles { get; set; } = new List<string>();
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
namespace tomware.OpenIddict.UI.Identity.Core
2+
{
3+
public class UserParam : UserInfo { }
4+
}

src/identity/OpenIddict.UI.Identity.Core/DependencyInjection.cs

+17-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,31 @@
11
using System.Diagnostics.CodeAnalysis;
2+
using Microsoft.AspNetCore.Identity;
23
using Microsoft.Extensions.DependencyInjection;
34

45
namespace tomware.OpenIddict.UI.Identity.Core
56
{
67
[ExcludeFromCodeCoverage]
78
public static class OpenIddictUIIdentityCoreServicesExtensions
89
{
9-
public static IServiceCollection AddOpenIddictUIIdentityCoreServices(
10+
public static IServiceCollection AddOpenIddictUIIdentityCoreServices<TApplicationUser>(
1011
this IServiceCollection services
11-
)
12+
) where TApplicationUser : IdentityUser, new()
1213
{
1314
services.AddTransient<IClaimTypeService, ClaimTypeService>();
15+
services.AddTransient<IUserCreationStrategy<TApplicationUser>, EmailUserCreationStrategy<TApplicationUser>>();
16+
17+
return services;
18+
}
19+
20+
/// <summary>
21+
/// Registers the UserName to UserName UserCreationStrategy.
22+
/// </summary>
23+
public static IServiceCollection AddUserNameUserCreationStrategy<TApplicationUser>(
24+
this IServiceCollection services
25+
) where TApplicationUser : IdentityUser, new()
26+
{
27+
services
28+
.AddTransient<IUserCreationStrategy<TApplicationUser>, UserNameUserCreationStrategy<TApplicationUser>>();
1429

1530
return services;
1631
}

0 commit comments

Comments
 (0)