Skip to content

Commit 41dabea

Browse files
committed
Added Switching Between Organization Units
1 parent ab76087 commit 41dabea

1 file changed

Lines changed: 136 additions & 0 deletions

File tree

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Switching Between Organization Units
2+
3+
In ASP.NET Zero projects, the ability for users to switch between different organizational units is essential, especially for multi unit organizations.Allowing users to select and change their active unit during their sessions enhances both the user experience and operational efficiency. However, managing this transition correctly and securely can often be complex.
4+
5+
## Implementing of Organization Unit Switching Between
6+
7+
In this section, we'll delve into the implementation details of enabling users to switch between different organizational units within an ASP.NET Zero project.
8+
9+
### Creating Claims Principal for Organization Unit
10+
11+
In this section, we create this functionality by overriding the **CreateAsync** function within the `UserClaimsPrincipalFactory` class. This modification ensures that we can access the organizational unit information for logged-in users.
12+
13+
```csharp
14+
public override async Task<ClaimsPrincipal> CreateAsync(User user)
15+
{
16+
var userWithOrgUnits = await GetUserWithOrganizationUnitsAsync(user.Id);
17+
18+
var claim = await base.CreateAsync(userWithOrgUnits);
19+
20+
string organizationUnitsJson = JsonSerializer.Serialize(userWithOrgUnits.OrganizationUnits.First());
21+
22+
claim.Identities.First().AddClaim(new Claim("Organization_Unit", organizationUnitsJson));
23+
24+
return claim;
25+
}
26+
```
27+
28+
The first code snippet overrides the **CreateAsync** method to incorporate organization unit information into the claims principal.
29+
30+
Within this context, we add the first element of the Organization Unit as a claim during user principal creation.
31+
32+
```csharp
33+
private async Task<User> GetUserWithOrganizationUnitsAsync(long userId)
34+
{
35+
return await UserManager.Users
36+
.Include(u => u.OrganizationUnits)
37+
.Where(x => x.Id == userId)
38+
.FirstOrDefaultAsync();
39+
}
40+
```
41+
42+
The second snippet demonstrates the asynchronous method GetUserWithOrganizationUnitsAsync, which retrieves a user with their associated organization units from the database.
43+
44+
### Modifying the Organization Unit in Session
45+
46+
Here, we implement functionality to modify the organizational unit within the session, following the guidelines outlined in this [document](https://aspnetboilerplate.com/Pages/Documents/Articles%5CHow-To%5Cadd-custom-session-field-aspnet-core).
47+
48+
```csharp
49+
public class MyAppSession : ClaimsAbpSession, ITransientDependency
50+
{
51+
private const string OrganizationUnitClaimTypeName = "Organization_Unit";
52+
private readonly UserManager _userManager;
53+
public MyAppSession(
54+
IPrincipalAccessor principalAccessor,
55+
IMultiTenancyConfig multiTenancy,
56+
ITenantResolver tenantResolver,
57+
IAmbientScopeProvider<SessionOverride> sessionOverrideScopeProvider,
58+
UserManager userManager) :
59+
base(principalAccessor, multiTenancy, tenantResolver, sessionOverrideScopeProvider)
60+
{
61+
_userManager = userManager;
62+
}
63+
64+
public string OrganizationUnit => PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == OrganizationUnitClaimTypeName)?.Value;
65+
66+
public async Task SwitchOrganizationUnitAsync(UserOrganizationUnit newUserOrganizationUnit)
67+
{
68+
var oldOrganizationUnit = JsonSerializer.Deserialize<UserOrganizationUnit>(OrganizationUnit);
69+
70+
SetOrganizationUnit(newUserOrganizationUnit);
71+
72+
await _userManager.RemoveFromOrganizationUnitAsync(oldOrganizationUnit.UserId, oldOrganizationUnit.OrganizationUnitId);
73+
}
74+
75+
private void SetOrganizationUnit(string newOrganizationUnit)
76+
{
77+
var identity = PrincipalAccessor.Principal?.Identity as ClaimsIdentity;
78+
if (identity != null)
79+
{
80+
var oldOrganizationUnitClaim = identity.FindFirst(OrganizationUnitClaimTypeName);
81+
if (oldOrganizationUnitClaim != null)
82+
{
83+
identity.RemoveClaim(oldOrganizationUnitClaim);
84+
}
85+
86+
identity.AddClaim(new Claim(OrganizationUnitClaimTypeName, newOrganizationUnit));
87+
}
88+
}
89+
}
90+
```
91+
92+
With these additions, the `MyAppSession` class now includes methods to both retrieve and set the organization unit information in the session. This enables management of organization unit data throughout the user's session.
93+
94+
### Usage Example: Switching Organization Units
95+
96+
In this section, we will demonstrate how to use a method for switching a user's organization unit within a new service class. The following example shows the `OrganizationUnitManager` class, which uses `MyAppSession` to allow a user to be removed from their current organization unit and added to a new one.
97+
98+
```csharp
99+
public class OrganizationUnitManager
100+
{
101+
private readonly MyAppSession _myAppSession;
102+
private readonly UserManager _userManager;
103+
104+
public OrganizationUnitManager(MyAppSession myAppSession, UserManager userManager)
105+
{
106+
_myAppSession = myAppSession;
107+
_userManager = userManager;
108+
}
109+
110+
public async Task SwitchOrganizationUnitAsync(UserOrganizationUnit newUserOrganizationUnit)
111+
{
112+
var oldOrganizationUnit = JsonSerializer.Deserialize<UserOrganizationUnit>(_myAppSession.OrganizationUnit);
113+
114+
_myAppSession.SetOrganizationUnit(newUserOrganizationUnit);
115+
116+
if (oldOrganizationUnit != null)
117+
{
118+
await _userManager.RemoveFromOrganizationUnitAsync(oldOrganizationUnit.UserId, oldOrganizationUnit.OrganizationUnitId);
119+
}
120+
121+
await _userManager.AddToOrganizationUnitAsync(newUserOrganizationUnit.UserId, newUserOrganizationUnit.OrganizationUnitId);
122+
}
123+
}
124+
```
125+
126+
#### Usage Steps
127+
128+
1. **Retrieve the Current Organization Unit:** The oldOrganizationUnit is deserialized from the current session's OrganizationUnit claim.
129+
2. **Set the New Organization Unit:** The SetOrganizationUnit method of MyAppSession is called to set the new organization unit in the session.
130+
3. **Remove from the Old Unit:** The user is removed from the old organization unit using _userManager.RemoveFromOrganizationUnitAsync.
131+
4. **Add to the New Unit:** The user is added to the new organization unit using _userManager.AddToOrganizationUnitAsync.
132+
133+
134+
## Conclusion
135+
136+
Switching between organizational units in ASP.NET Zero projects can increase your organization's flexibility in transitions between organizations and facilitate organizational management. With a custom session, it is possible to switch between the user's current organization information and the organization. This work can also simplify organizational operational processes.

0 commit comments

Comments
 (0)