diff --git a/Marco.Pms.Model/Dtos/Tenant/CreateTenantDto.cs b/Marco.Pms.Model/Dtos/Tenant/CreateTenantDto.cs new file mode 100644 index 0000000..bf4cf4a --- /dev/null +++ b/Marco.Pms.Model/Dtos/Tenant/CreateTenantDto.cs @@ -0,0 +1,44 @@ +using System.ComponentModel.DataAnnotations; + +namespace Marco.Pms.Model.Dtos.Tenant +{ + public class CreateTenantDto + { + [Required] + public string Username { get; set; } + + [Required] + [EmailAddress] + public string Email { get; set; } + + [Required] + [MinLength(6)] + [RegularExpression(@"^(?=.*[^a-zA-Z0-9])(?=.*\d)(?=.*[A-Z]).+$", ErrorMessage = "Passwords must have at least one non-alphanumeric character, at least one digit ('0'-'9'), and at least one uppercase ('A'-'Z').")] + public string Password { get; set; } + + + public string OrganizatioinName { get; set; } + public string? About { get; set; } + public string? OragnizationSize { get; set; } + public int IndustryId { get; set; } + public string Website { get; set; } + public string Name { get; set; } + public string ContactNumber { get; set; } + public DateTime OnBoardingDate { get; set; } + + //public string Gender { get; set; } + //public string? BirthDate { get; set; } + //public DateTime JoiningDate { get; set; } + + //public string? PeramnentAddress { get; set; } + //public string? CurrentAddress { get; set; } + + //public string EmergencyPhoneNumber { get; set; } + //public string EmergencyContactPerson { get; set; } + + //public string? AadharNumber { get; set; } + + //public string? PanNumber { get; set; } + + } +} diff --git a/Marco.Pms.Model/Entitlements/ApplicationRole.cs b/Marco.Pms.Model/Entitlements/ApplicationRole.cs index 512e99b..b972f66 100644 --- a/Marco.Pms.Model/Entitlements/ApplicationRole.cs +++ b/Marco.Pms.Model/Entitlements/ApplicationRole.cs @@ -1,8 +1,4 @@ -using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; -using System.ComponentModel; -using System.ComponentModel.DataAnnotations.Schema; - -namespace Marco.Pms.Model.Entitlements +namespace Marco.Pms.Model.Entitlements { public class ApplicationRole { diff --git a/Marco.Pms.Model/Entitlements/ApplicationUser.cs b/Marco.Pms.Model/Entitlements/ApplicationUser.cs index ef7770a..aa04986 100644 --- a/Marco.Pms.Model/Entitlements/ApplicationUser.cs +++ b/Marco.Pms.Model/Entitlements/ApplicationUser.cs @@ -9,8 +9,8 @@ namespace Marco.Pms.Model.Entitlements { public class ApplicationUser : IdentityUser { - [Required] - public string Role { get; set; } // e.g. Admin, SiteManager, SkilledWorker, etc. + //[Required] + // public string Role { get; set; } // e.g. Admin, SiteManager, SkilledWorker, etc. [DisplayName("TenantId")] diff --git a/Marco.Pms.Model/Entitlements/Client.cs b/Marco.Pms.Model/Entitlements/Client.cs index 1ce97dd..4494e63 100644 --- a/Marco.Pms.Model/Entitlements/Client.cs +++ b/Marco.Pms.Model/Entitlements/Client.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Marco.Pms.Model.Entitlements +namespace Marco.Pms.Model.Entitlements { public class Tenant { @@ -14,6 +8,9 @@ namespace Marco.Pms.Model.Entitlements public string DomainName { get; set; } public string ContactName { get; set; } public string ContactNumber { get; set; } + + //public string? OragnizationSize { get; set; } + //public int IndustryId { get; set; } public DateTime OnBoardingDate { get; set; } } } diff --git a/Marco.Pms.Model/Entitlements/FeaturePermission.cs b/Marco.Pms.Model/Entitlements/FeaturePermission.cs index 830807a..f7f33c7 100644 --- a/Marco.Pms.Model/Entitlements/FeaturePermission.cs +++ b/Marco.Pms.Model/Entitlements/FeaturePermission.cs @@ -1,12 +1,5 @@ -using Marco.Pms.Model.Projects; +using System.ComponentModel.DataAnnotations.Schema; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Data; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Marco.Pms.Model.Entitlements { diff --git a/Marco.Pms.Model/Entitlements/JobRole.cs b/Marco.Pms.Model/Entitlements/JobRole.cs index 3557525..d89f317 100644 --- a/Marco.Pms.Model/Entitlements/JobRole.cs +++ b/Marco.Pms.Model/Entitlements/JobRole.cs @@ -1,5 +1,5 @@ -using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; namespace Marco.Pms.Model.Entitlements { diff --git a/Marco.Pms.Model/Mapper/TenantMapper.cs b/Marco.Pms.Model/Mapper/TenantMapper.cs new file mode 100644 index 0000000..9cfd660 --- /dev/null +++ b/Marco.Pms.Model/Mapper/TenantMapper.cs @@ -0,0 +1,23 @@ +using Marco.Pms.Model.Dtos.Tenant; +using Marco.Pms.Model.Employees; +using Marco.Pms.Model.Entitlements; + +namespace Marco.Pms.Model.Mapper +{ + public static class TenantMapper + { + public static Tenant CreateDtoToTenant(this CreateTenantDto createTenant) + { + return new Tenant + { + Name = createTenant.OrganizatioinName, + Description = createTenant.About, + DomainName = createTenant.Website, + ContactName = createTenant.Name, + ContactNumber = createTenant.ContactNumber, + OnBoardingDate = createTenant.OnBoardingDate, + }; + } + + } +} diff --git a/Marco.Pms.Model/Utilities/RolesConfiguration.cs b/Marco.Pms.Model/Utilities/RolesConfiguration.cs new file mode 100644 index 0000000..4eb9b1f --- /dev/null +++ b/Marco.Pms.Model/Utilities/RolesConfiguration.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Marco.Pms.Model.Utilities +{ + public class RoleConfiguration + { + public string JobRoleName { get; set; } + public string JobRoleDescription { get; set; } + public string RoleName { get; set; } + public string RoleDescription { get; set; } + } +} diff --git a/Marco.Pms.Services/Controllers/TenantController.cs b/Marco.Pms.Services/Controllers/TenantController.cs new file mode 100644 index 0000000..efe9485 --- /dev/null +++ b/Marco.Pms.Services/Controllers/TenantController.cs @@ -0,0 +1,153 @@ +using Marco.Pms.DataAccess.Data; +using Marco.Pms.Model.Dtos.Tenant; +using Marco.Pms.Model.Employees; +using Marco.Pms.Model.Entitlements; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Marco.Pms.Model.Mapper; +using System.Text.Json; +using Marco.Pms.Model.Utilities; + +namespace Marco.Pms.Services.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class TenantController : ControllerBase + { + private readonly string jsonString = System.IO.File.ReadAllText("Data/RolesCofiguration.json"); + private readonly ApplicationDbContext _context; + private readonly UserManager _userManager; + public TenantController(ApplicationDbContext context,UserManager userManager) + { + _context = context; + _userManager = userManager; + } + [HttpPost] + public async Task CreateTenant([FromForm] CreateTenantDto createTenantDto) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + if (await _userManager.FindByEmailAsync(createTenantDto.Email) != null) + { + return BadRequest("Tenant Already Exists"); + } + + Tenant newTenant = createTenantDto.CreateDtoToTenant(); + _context.Tenants.Add(newTenant); + await _context.SaveChangesAsync(); + Tenant? tenant = await _context.Tenants.AsNoTracking().FirstOrDefaultAsync(t => t.Name == newTenant.Name); + if (tenant != null) + { + RoleConfiguration settings = JsonSerializer.Deserialize(jsonString); + var TenantId = tenant.Id; + JobRole jobRole = new JobRole + { + Name = settings.JobRoleName, + Description = settings.JobRoleDescription, + TenantId = TenantId + }; + ApplicationRole role = new ApplicationRole + { + Role = settings.RoleName, + Description = settings.JobRoleDescription, + TenantId = TenantId + }; + if (_context.JobRoles.AsNoTracking().FirstOrDefaultAsync(r => r.Name == "Admin") != null) + { + _context.JobRoles.Add(jobRole); + await _context.SaveChangesAsync(); + } + if (_context.JobRoles.AsNoTracking().FirstOrDefaultAsync(r => r.Name == "SuperUser") != null) + { + _context.ApplicationRoles.Add(role); + await _context.SaveChangesAsync(); + } + List permissions = await _context.FeaturePermissions.AsNoTracking().ToListAsync(); + //List < RolePermissionMappings > = []; + foreach(var permission in permissions) + { + var item = new RolePermissionMappings() { ApplicationRoleId = role.Id, FeaturePermissionId = permission.Id }; + bool assigned = _context.RolePermissionMappings.Any(c => c.ApplicationRoleId == role.Id && c.FeaturePermissionId == permission.Id); + if (permission.IsEnabled && !assigned) + _context.RolePermissionMappings.Add(item); + } + await _context.SaveChangesAsync(); + var user = new ApplicationUser + { + UserName = createTenantDto.Username, + Email = createTenantDto.Email, + TenantId = TenantId, + IsRootUser = true, + EmailConfirmed = true + }; + + var result = await _userManager.CreateAsync(user, createTenantDto.Password); + if (result.Succeeded) + { + Employee newEmployee = CreateTenantDtoToEmployee(createTenantDto, TenantId, user.Id,jobRole.Id); + _context.Employees.Add(newEmployee); + await _context.SaveChangesAsync(); + + var employeeRoleMapping = new EmployeeRoleMapping + { + EmployeeId = newEmployee.Id, + RoleId = role.Id, + TenantId = TenantId, + IsEnabled = true + }; + _context.EmployeeRoleMappings.Add(employeeRoleMapping); + await _context.SaveChangesAsync(); + return Ok(newEmployee); + } + else + { + // Log the errors for debugging + foreach (var error in result.Errors) + { + // Log error.Description + Console.WriteLine($"UserManager Error: {error.Description}"); + } + return BadRequest("Failed to create the root user."); + } + } + return BadRequest("Falied to create Tenant"); + + } + private static Employee CreateTenantDtoToEmployee(CreateTenantDto model, int TenantId, string? ApplicationUserId,int jobRoleId) + { + return new Employee + { + ApplicationUserId = ApplicationUserId, + //FirstName = model.FirstName, + FirstName = model.Name, + //LastName = model.LastName, + LastName = "", + Email = model.Email, + TenantId = TenantId, + CurrentAddress = "", + BirthDate = DateTime.UtcNow, + EmergencyPhoneNumber = "", + EmergencyContactPerson = "", + AadharNumber = "", + Gender = "", + //MiddleName = model.MiddleName, + MiddleName = "", + PanNumber = "", + PeramnentAddress = "", + PhoneNumber = "", + Photo = null, // GetFileDetails(model.Photo).Result.FileData, + //JobRoleId = Convert.ToInt32(model.JobRoleId), + JobRoleId = jobRoleId, + JoiningDate = DateTime.UtcNow, + + }; + } + + + } + +} diff --git a/Marco.Pms.Services/Data/RolesCofiguration.json b/Marco.Pms.Services/Data/RolesCofiguration.json new file mode 100644 index 0000000..9400eab --- /dev/null +++ b/Marco.Pms.Services/Data/RolesCofiguration.json @@ -0,0 +1,6 @@ +{ + "JobRoleName": "Admin", + "JobRoleDescription": "Admin", + "RoleName": "SuperRole", + "RoleDescription": "SuperRole" +} \ No newline at end of file diff --git a/Marco.Pms.Services/Program.cs b/Marco.Pms.Services/Program.cs index dda2b5f..846f989 100644 --- a/Marco.Pms.Services/Program.cs +++ b/Marco.Pms.Services/Program.cs @@ -166,9 +166,13 @@ app.UseCors("Policy"); app.UseStaticFiles(); // Enables serving static files +<<<<<<< HEAD //app.UseSerilogRequestLogging(); // This is Default Serilog Logging Middleware we are not using this because we're using custom logging middleware +======= +//app.UseSerilogRequestLogging(); // Log HTTP requests +>>>>>>> Created new API for creating new tenant app.UseHttpsRedirection(); app.UseMiddleware(); app.UseMiddleware(); diff --git a/Marco.Pms.Services/appsettings.json b/Marco.Pms.Services/appsettings.json index bb0e7e5..ae0ac78 100644 --- a/Marco.Pms.Services/appsettings.json +++ b/Marco.Pms.Services/appsettings.json @@ -64,8 +64,13 @@ "ConnectionStrings": { // "DefaultConnectionString": "Server=103.50.160.45;User ID=marcowvh_admin;Password=Marcoemp@123;Database=marcowvh_empattendanceci", +<<<<<<< HEAD //"DefaultConnectionString": "Server=localhost;port=3333;User ID=root;Password=root;Database=MarcoBMS1", "DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1" +======= + "DefaultConnectionString": "Server=localhost;port=3333;User ID=root;Password=root;Database=MarcoBMS1", + //"DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1" +>>>>>>> Created new API for creating new tenant }, "AppSettings": { "WebFrontendUrl": "http://localhost:5173",