NOTE: I am not sure if this is the correct place for this kind of questions. Although most questions ask about code, I also saw some questions regarding UML and diagrams. PLEASE, let me know if I've done an oopsie and I will immediately delete this post. Also, this post will contain quite a bit of code so I could explain better what is going on in the code.
I started working on a Domain Model for my code (I know, the Domain Model should have been first) but I have issues figuring out how the arrows between my classes should look like. From what I have read I got a slight idea but I am still rather confused.
Firstly this is a link to my domain model.
User
is used as a model when creating a new AppUser
, class which is an implementation of IdentityUser
.
AppUser
is used only when you want to Login
. I am really not sure if there is any relationship between these two classes. Below you can see the only part where these two classes are involved together.
public async Task<IActionResult> Login(Login login)
{
if (ModelState.IsValid)
{
AppUser appUser = await userManager.FindByEmailAsync(login.Email);
if (appUser != null)
{
await signInManager.SignOutAsync();
Microsoft.AspNetCore.Identity.SignInResult result = await signInManager.PasswordSignInAsync(appUser, login.Password, false, false);
if (result.Succeeded)
return Redirect(login.ReturnUrl ?? "/");
}
ModelState.AddModelError(nameof(login.Email), "Login Failed: Invalid Email or password");
}
return View(login);
}
RoleEdit
and RoleModification
are used to assign an entry from dbo.AspNetUsers
to a role from dbo.AspNetRoles
.
public async Task<IActionResult> Update(string id)
{
IdentityRole role = await roleManager.FindByIdAsync(id);
List<AppUser> members = new List<AppUser>();
List<AppUser> nonMembers = new List<AppUser>();
foreach (AppUser user in userManager.Users)
{
var list = await userManager.IsInRoleAsync(user, role.Name) ? members : nonMembers;
list.Add(user);
}
return View(new RoleEdit
{
Role = role,
Members = members,
NonMembers = nonMembers
});
}
[HttpPost]
public async Task<IActionResult> Update(RoleModification model)
{
IdentityResult result;
if (ModelState.IsValid)
{
foreach (string userId in model.AddIds ?? new string[] { })
{
AppUser user = await userManager.FindByIdAsync(userId);
if (user != null)
{
result = await userManager.AddToRoleAsync(user, model.RoleName);
if (!result.Succeeded)
Errors(result);
}
}
foreach (string userId in model.DeleteIds ?? new string[] { })
{
AppUser user = await userManager.FindByIdAsync(userId);
if (user != null)
{
result = await userManager.RemoveFromRoleAsync(user, model.RoleName);
if (!result.Succeeded)
Errors(result);
}
}
}
if (ModelState.IsValid)
return RedirectToAction(nameof(Index));
else
return await Update(model.RoleId);
}
An Application
can have many Releases
. If an application is deleted, its releases will also be deleted. Also, an Application
must be issued a single Environment
(such as Development, Testing, etc.)
A Release
can have many Phases
. If a release is deleted, its phases will also be deleted. Same as the Applications, a Release
must be issued to a single Stage
.
A Phase
can have many Tasks
. If a phase is deleted, its tasks won't be deleted.
A Task
can have many Dependencies
.
AppIdentityDbContext
is a class used for the connection with the database.
ErrorViewModel
is a class that I used only once and is not really important. Should it be kept in the Domain Model?
I think that's pretty much it. The Domain Model that I gave you the link to is not yet done as I was unsure whether I am doing the right thing or not. Any help, advice, hints that you could give me are incredibly important and welcome!
Thanks to whoever read this lengthy post and could help me out.
The relation between login and user...login is used to capture the information from the login form, you are then using that info to find the user in the system and verify that they are in the system. They are not linked in your domain model because the login class has a return url in case they need to be redirected and is used to just log someone in. They have separate function and under the premise of programming in an MVC pattern you are separating your concerns which is a good practice.
ViewModels are models so you can expose domain data to your view but is not part of the domain so ErrorViewModel does not need it be included in your diagram.
If modification history is important to you I would suggest a ModifiedBy and ModifiedDate field for the classes you feel it is important to track that info. You can also add another field 'Deleted' so if someone deletes something that wasnt supposed to be you can revert that change. You can also add a 'LastLogin" dateTime field to the user to track users activity.