From 3a7edb23c74e61fe2f5241159164f7ed5eef0429 Mon Sep 17 00:00:00 2001 From: Bangara Raju Kottedi Date: Sat, 22 Nov 2025 06:52:59 +0530 Subject: [PATCH 1/5] Add JWT, OTP, and caching features Upgraded projects to .NET 9.0 and added new projects `KBR.Cache`, `KBR.Shared`, and `KBR.Shared.Lite` to the solution. Introduced JWT authentication and OTP handling with new models, services, and configuration options. Updated database schema with new entities `Users` and `RefreshTokens`, and added migrations for schema changes. Implemented caching strategies using `AppDistributedCache` with support for in-memory, SQL Server, and Redis. Enhanced email handling with `MailHelpers` for domain replacement. Updated controllers, repositories, and configuration files to support new features. --- AesEncryption/AesEncryption.csproj | 2 +- PortBlog.API.sln | 25 + .../Common/{ => Constants}/MailConstants.cs | 2 +- PortBlog.API/Common/Constants/OptionNames.cs | 9 + PortBlog.API/Controllers/AdminController.cs | 160 ++ PortBlog.API/Controllers/AuthController.cs | 184 ++ PortBlog.API/Controllers/BlogController.cs | 1 - PortBlog.API/Controllers/CvController.cs | 4 +- PortBlog.API/DbContexts/CvBlogContext.cs | 9 + PortBlog.API/DbContexts/Seed/InitialData.cs | 14 +- PortBlog.API/Entities/Cache.cs | 11 + PortBlog.API/Entities/Mapping/CacheMapping.cs | 17 + PortBlog.API/Entities/Message.cs | 1 - PortBlog.API/Entities/RefreshToken.cs | 33 + PortBlog.API/Entities/User.cs | 19 + PortBlog.API/Extensions/ServiceExtensions.cs | 2 + ...0251001130551_CreateCacheTable.Designer.cs | 1393 ++++++++++++++++ .../20251001130551_CreateCacheTable.cs | 515 ++++++ ...082117_MessageContentMaxLength.Designer.cs | 1392 +++++++++++++++ .../20251008082117_MessageContentMaxLength.cs | 517 ++++++ ...51028060442_User_RefreshTokens.Designer.cs | 1392 +++++++++++++++ .../20251028060442_User_RefreshTokens.cs | 495 ++++++ ...62356_User_RefreshTokens_Rerun.Designer.cs | 1485 +++++++++++++++++ ...20251028062356_User_RefreshTokens_Rerun.cs | 561 +++++++ ...5746_User_RefreshTokens_Update.Designer.cs | 1485 +++++++++++++++++ ...0251029015746_User_RefreshTokens_Update.cs | 509 ++++++ ...1113135040_update-refreshtoken.Designer.cs | 1484 ++++++++++++++++ .../20251113135040_update-refreshtoken.cs | 537 ++++++ .../Migrations/CvBlogContextModelSnapshot.cs | 261 ++- PortBlog.API/Models/MailSettingsDto.cs | 2 + PortBlog.API/Models/MessageSendDto.cs | 2 - PortBlog.API/Models/OtpMailModel.cs | 9 + PortBlog.API/Models/VerifyOtpRequest.cs | 8 + .../Options/JwtAuthenticationOptions.cs | 11 + PortBlog.API/PortBlog.API.csproj | 28 +- PortBlog.API/PortBlog.API.xml | 136 ++ PortBlog.API/Program.cs | 100 +- PortBlog.API/Properties/launchSettings.json | 35 +- .../Repositories/CandidateRepository.cs | 5 + .../Contracts/ICandidateRepository.cs | 2 + PortBlog.API/Services/AuthService.cs | 153 ++ .../Services/Contracts/IAuthService.cs | 23 + .../Services/Contracts/IOtpService.cs | 6 + .../Services/Contracts/ITemplateService.cs | 7 + .../Services/Contracts/ITokenService.cs | 6 + .../Services/Contracts/JwtServicecs.cs | 6 + PortBlog.API/Services/JwtService.cs | 6 + PortBlog.API/Services/MailService.cs | 16 +- PortBlog.API/Services/OtpService.cs | 6 + PortBlog.API/Services/TemplateService.cs | 13 + PortBlog.API/Services/TokenService.cs | 6 + .../Views/Email/OtpEmailTemplate.cshtml | 67 + PortBlog.API/appsettings.Development.json | 23 +- Shared/KBR.Cache/AppDistributedCache.cs | 96 ++ Shared/KBR.Cache/CacheHelpers.cs | 24 + Shared/KBR.Cache/Constants/CacheProviders.cs | 11 + .../Extensions/ServiceCollectionExtensions.cs | 47 + Shared/KBR.Cache/IAppDistributedCache.cs | 27 + Shared/KBR.Cache/KBR.Cache.csproj | 26 + Shared/KBR.Cache/Options/CacheOptions.cs | 9 + .../Extensions/JsonExtensions.cs | 76 + Shared/KBR.Share.Lite/KBR.Shared.Lite.csproj | 13 + Shared/KBR.Shared/Cache/CacheExtensions.cs | 28 + Shared/KBR.Shared/Cache/CacheHelpers.cs | 21 + .../KBR.Shared/Cache/IAppDistributedCache.cs | 27 + .../Cache/Models/UserSessionModel.cs | 15 + Shared/KBR.Shared/KBR.Shared.csproj | 17 + Shared/KBR.Shared/Mail/MailHelpers.cs | 21 + 68 files changed, 13506 insertions(+), 147 deletions(-) rename PortBlog.API/Common/{ => Constants}/MailConstants.cs (83%) create mode 100644 PortBlog.API/Common/Constants/OptionNames.cs create mode 100644 PortBlog.API/Controllers/AdminController.cs create mode 100644 PortBlog.API/Controllers/AuthController.cs create mode 100644 PortBlog.API/Entities/Cache.cs create mode 100644 PortBlog.API/Entities/Mapping/CacheMapping.cs create mode 100644 PortBlog.API/Entities/RefreshToken.cs create mode 100644 PortBlog.API/Entities/User.cs create mode 100644 PortBlog.API/Migrations/20251001130551_CreateCacheTable.Designer.cs create mode 100644 PortBlog.API/Migrations/20251001130551_CreateCacheTable.cs create mode 100644 PortBlog.API/Migrations/20251008082117_MessageContentMaxLength.Designer.cs create mode 100644 PortBlog.API/Migrations/20251008082117_MessageContentMaxLength.cs create mode 100644 PortBlog.API/Migrations/20251028060442_User_RefreshTokens.Designer.cs create mode 100644 PortBlog.API/Migrations/20251028060442_User_RefreshTokens.cs create mode 100644 PortBlog.API/Migrations/20251028062356_User_RefreshTokens_Rerun.Designer.cs create mode 100644 PortBlog.API/Migrations/20251028062356_User_RefreshTokens_Rerun.cs create mode 100644 PortBlog.API/Migrations/20251029015746_User_RefreshTokens_Update.Designer.cs create mode 100644 PortBlog.API/Migrations/20251029015746_User_RefreshTokens_Update.cs create mode 100644 PortBlog.API/Migrations/20251113135040_update-refreshtoken.Designer.cs create mode 100644 PortBlog.API/Migrations/20251113135040_update-refreshtoken.cs create mode 100644 PortBlog.API/Models/OtpMailModel.cs create mode 100644 PortBlog.API/Models/VerifyOtpRequest.cs create mode 100644 PortBlog.API/Options/JwtAuthenticationOptions.cs create mode 100644 PortBlog.API/Services/AuthService.cs create mode 100644 PortBlog.API/Services/Contracts/IAuthService.cs create mode 100644 PortBlog.API/Services/Contracts/IOtpService.cs create mode 100644 PortBlog.API/Services/Contracts/ITemplateService.cs create mode 100644 PortBlog.API/Services/Contracts/ITokenService.cs create mode 100644 PortBlog.API/Services/Contracts/JwtServicecs.cs create mode 100644 PortBlog.API/Services/JwtService.cs create mode 100644 PortBlog.API/Services/OtpService.cs create mode 100644 PortBlog.API/Services/TemplateService.cs create mode 100644 PortBlog.API/Services/TokenService.cs create mode 100644 PortBlog.API/Views/Email/OtpEmailTemplate.cshtml create mode 100644 Shared/KBR.Cache/AppDistributedCache.cs create mode 100644 Shared/KBR.Cache/CacheHelpers.cs create mode 100644 Shared/KBR.Cache/Constants/CacheProviders.cs create mode 100644 Shared/KBR.Cache/Extensions/ServiceCollectionExtensions.cs create mode 100644 Shared/KBR.Cache/IAppDistributedCache.cs create mode 100644 Shared/KBR.Cache/KBR.Cache.csproj create mode 100644 Shared/KBR.Cache/Options/CacheOptions.cs create mode 100644 Shared/KBR.Share.Lite/Extensions/JsonExtensions.cs create mode 100644 Shared/KBR.Share.Lite/KBR.Shared.Lite.csproj create mode 100644 Shared/KBR.Shared/Cache/CacheExtensions.cs create mode 100644 Shared/KBR.Shared/Cache/CacheHelpers.cs create mode 100644 Shared/KBR.Shared/Cache/IAppDistributedCache.cs create mode 100644 Shared/KBR.Shared/Cache/Models/UserSessionModel.cs create mode 100644 Shared/KBR.Shared/KBR.Shared.csproj create mode 100644 Shared/KBR.Shared/Mail/MailHelpers.cs diff --git a/AesEncryption/AesEncryption.csproj b/AesEncryption/AesEncryption.csproj index 4c9fd05..63bbe21 100644 --- a/AesEncryption/AesEncryption.csproj +++ b/AesEncryption/AesEncryption.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable false diff --git a/PortBlog.API.sln b/PortBlog.API.sln index 22ea6e5..cbbed79 100644 --- a/PortBlog.API.sln +++ b/PortBlog.API.sln @@ -7,6 +7,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortBlog.API", "PortBlog.AP EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AesEncryption", "AesEncryption\AesEncryption.csproj", "{26654BFD-EE9B-49BA-84BA-9156AC348076}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{868B8641-C2BB-415C-816A-4FB477DA009B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KBR.Cache", "Shared\KBR.Cache\KBR.Cache.csproj", "{DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KBR.Shared", "Shared\KBR.Shared\KBR.Shared.csproj", "{1C0F86E4-A791-4150-B9B3-B761925681DD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KBR.Shared.Lite", "Shared\KBR.Share.Lite\KBR.Shared.Lite.csproj", "{F4B7078B-C59A-46B8-881A-C3CEE2634498}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,10 +29,27 @@ Global {26654BFD-EE9B-49BA-84BA-9156AC348076}.Debug|Any CPU.Build.0 = Debug|Any CPU {26654BFD-EE9B-49BA-84BA-9156AC348076}.Release|Any CPU.ActiveCfg = Release|Any CPU {26654BFD-EE9B-49BA-84BA-9156AC348076}.Release|Any CPU.Build.0 = Release|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Release|Any CPU.Build.0 = Release|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Release|Any CPU.Build.0 = Release|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA} = {868B8641-C2BB-415C-816A-4FB477DA009B} + {1C0F86E4-A791-4150-B9B3-B761925681DD} = {868B8641-C2BB-415C-816A-4FB477DA009B} + {F4B7078B-C59A-46B8-881A-C3CEE2634498} = {868B8641-C2BB-415C-816A-4FB477DA009B} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B74EF3B9-68FB-42A1-9635-817DFB28CD9E} EndGlobalSection diff --git a/PortBlog.API/Common/MailConstants.cs b/PortBlog.API/Common/Constants/MailConstants.cs similarity index 83% rename from PortBlog.API/Common/MailConstants.cs rename to PortBlog.API/Common/Constants/MailConstants.cs index 6024ed2..1e97c14 100644 --- a/PortBlog.API/Common/MailConstants.cs +++ b/PortBlog.API/Common/Constants/MailConstants.cs @@ -1,4 +1,4 @@ -namespace PortBlog.API.Common +namespace PortBlog.API.Common.Constants { public static class MailConstants { diff --git a/PortBlog.API/Common/Constants/OptionNames.cs b/PortBlog.API/Common/Constants/OptionNames.cs new file mode 100644 index 0000000..57714ae --- /dev/null +++ b/PortBlog.API/Common/Constants/OptionNames.cs @@ -0,0 +1,9 @@ +namespace PortBlog.API.Common.Constants +{ + public static class OptionNames + { + public const string JwtAuthentication = nameof(JwtAuthentication); + + public const string OtpExpiryInMinutes = nameof(OtpExpiryInMinutes); + } +} diff --git a/PortBlog.API/Controllers/AdminController.cs b/PortBlog.API/Controllers/AdminController.cs new file mode 100644 index 0000000..56905bf --- /dev/null +++ b/PortBlog.API/Controllers/AdminController.cs @@ -0,0 +1,160 @@ +using Asp.Versioning; +using AutoMapper; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using PortBlog.API.Models; +using PortBlog.API.Repositories.Contracts; +using PortBlog.API.Services.Contracts; + +namespace PortBlog.API.Controllers +{ + [Route("api/v{version:apiVersion}/admin")] + [ApiController] + [ApiVersion(1)] + [Authorize] + public class AdminController : Controller + { + private readonly ILogger _logger; + private readonly ICandidateRepository _candidateRepository; + private readonly IResumeRepository _resumeRepository; + private readonly IMapper _mapper; + public AdminController(ILogger logger, ICandidateRepository candidateRepository, IResumeRepository resumeRepository, IMailService mailService, IMapper mapper, IMailRepository mailRepository) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _candidateRepository = candidateRepository ?? throw new ArgumentNullException(nameof(candidateRepository)); + _resumeRepository = resumeRepository ?? throw new ArgumentNullException(nameof(resumeRepository)); + _mapper = mapper; + } + /// + /// Get hobbies of the candidate by candidateid + /// + /// The id of the candidate whose hobbies to get + /// Hobbies of the candidate + /// Returns the requested hobbies of the candidate + [HttpGet("GetHobbies/{candidateId}")] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> GetHobbies(int candidateId) + { + try + { + if (!await _candidateRepository.CandidateExistAsync(candidateId)) + { + _logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching about details."); + return NotFound(); + } + + var aboutDetails = await _resumeRepository.GetHobbiesAsync(candidateId); + + return Ok(_mapper.Map(aboutDetails)); + + } + catch (Exception ex) + { + _logger.LogCritical($"Exception while getting about details for the candidate with id {candidateId}.", ex); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Get Candidate details with social links by candidateid + /// + /// The id of the candidate whose detials to get with social links + /// Candidate details with sociallinks + /// Returns the requested candidate details with social links + [HttpGet("GetCandidateWithSocialLinks/{candidateId}")] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> GetContact(int candidateId) + { + try + { + if (!await _candidateRepository.CandidateExistAsync(candidateId)) + { + _logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching candidate with social links."); + return NotFound(); + } + + var contact = await _resumeRepository.GetCandidateWithSocialLinksAsync(candidateId); + + return Ok(_mapper.Map(contact)); + + } + catch (Exception ex) + { + _logger.LogCritical($"Exception while getting contact for the candidate with social links with id {candidateId}.", ex); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Get Candidate resume by candidateid + /// + /// The id of the candidate whose resume to get + /// Candidate resume + /// Returns the requested candidate resume + [HttpGet("GetResume/{candidateId}")] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> GetResume(int candidateId) + { + try + { + if (!await _candidateRepository.CandidateExistAsync(candidateId)) + { + _logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching resume."); + return NotFound(); + } + + var resume = await _resumeRepository.GetResumeAsync(candidateId); + + return Ok(_mapper.Map(resume)); + + } + catch (Exception ex) + { + _logger.LogCritical($"Exception while getting resume for the candidate with id {candidateId}.", ex); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Get Candidate projects by candidateid + /// + /// The id of the candidate whose projects to get + /// Candidate projects + /// Returns the requested candidate projects + [HttpGet("GetProjects/{candidateId}")] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> GetProjects(int candidateId) + { + try + { + if (!await _candidateRepository.CandidateExistAsync(candidateId)) + { + _logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching projects."); + return NotFound(); + } + + var projects = await _resumeRepository.GetProjectsAsync(candidateId); + + return Ok(_mapper.Map(projects)); + + } + catch (Exception ex) + { + _logger.LogCritical($"Exception while getting projects for the candidate with id {candidateId}.", ex); + return StatusCode(500, "A problem happened while handling your request."); + } + } + } +} diff --git a/PortBlog.API/Controllers/AuthController.cs b/PortBlog.API/Controllers/AuthController.cs new file mode 100644 index 0000000..f2d5983 --- /dev/null +++ b/PortBlog.API/Controllers/AuthController.cs @@ -0,0 +1,184 @@ +using Asp.Versioning; +using AutoMapper; +using Azure.Core; +using KBR.Cache; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using PortBlog.API.Entities; +using PortBlog.API.Models; +using PortBlog.API.Repositories.Contracts; +using PortBlog.API.Services; +using PortBlog.API.Services.Contracts; +using System.Threading.Tasks; + +namespace PortBlog.API.Controllers +{ + /// + /// Controller for handling authentication-related operations. + /// + [Route("api/v{version:apiVersion}/auth")] + [ApiController] + [ApiVersion(1)] + public class AuthController(IAuthService authService, IMailService mailService, ICandidateRepository candidateRepository, ILogger logger, IMapper mapper, IConfiguration configuration, ITemplateService templateService, IAppDistributedCache cache) : ControllerBase + { + /// + /// Generates a One-Time Password (OTP) for the specified candidate and sends it via email. + /// + /// The ID of the candidate for whom the OTP is generated. + /// An ActionResult indicating the result of the operation. + [HttpPost("GenerateOtp")] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task GenerateOtp([FromForm] string email) + { + var messageSendDto = new MessageSendDto(); + try + { + var candidate = await candidateRepository.GetCandidateAsync(email); + if (candidate == null) + { + logger.LogInformation($"Candidate with email ({email}) wasn't found."); + return NotFound(); + } + + var candidateDto = mapper.Map(candidate); + var otp = await authService.GenerateOtp(email); + + var otpModel = new OtpMailModel() + { + OtpCode = otp, + Name = candidateDto.DisplayName, + ExpiryMinutes = configuration.GetValue("OtpExpiryInMinutes", 3) + }; + + messageSendDto.CandidateId = candidate.CandidateId; + messageSendDto.ToEmail = candidateDto.Email; + messageSendDto.Name = candidateDto.DisplayName; + messageSendDto.Subject = "OTP for Login"; + messageSendDto.Content = await templateService.GetViewTemplate("Views/Email/OtpEmailTemplate.cshtml", otpModel); + await mailService.SendAsync(messageSendDto); + return Ok(true); + } + catch (Exception ex) + { + logger.LogCritical($"Exception while sending OTP for {messageSendDto.ToEmail}.", ex); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Verifies the One-Time Password (OTP) for the specified user. + /// + /// The request containing the user ID and OTP code to verify. + /// An ActionResult indicating the result of the verification. + [HttpPost("ValidateOtp")] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task VerifyOtp([FromBody] VerifyOtpRequest request) + { + try + { + if (request == null || string.IsNullOrEmpty(request.UserId) || string.IsNullOrEmpty(request.OtpCode)) + return BadRequest(new { message = "Invalid request data." }); + + var secretKey = await CacheHelpers.GetUserOtpSecretAsync(cache, request.UserId); + + if(secretKey == null) + { + return Unauthorized(new { message = "OTP Expired" }); + } + + var result = authService.ValidateOtp(secretKey, request.OtpCode); + + if (!result) + return Unauthorized(new { message = "Invalid OTP" }); + + + var accessToken = authService.GenerateAccessToken(request.UserId); + var refreshToken = authService.GenerateRefreshToken(); + + // Store hashed refresh token in DB + await authService.SaveRefreshToken(request.UserId, refreshToken, HttpContext); + + // Set HttpOnly cookie + SetRefreshTokenCookie(refreshToken); + + return Ok(new { accessToken }); // only access token is returned in response body + } + catch (Exception ex) + { + logger.LogCritical($"Exception while validating OTP for {request.UserId}.", ex); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + [HttpPost("RefreshToken")] + public async Task Refresh() + { + // Read refresh token from HttpOnly cookie + if (!Request.Cookies.TryGetValue("refreshToken", out var refreshToken)) + return Unauthorized(); + + var matchedToken = await authService.GetRefreshTokenAsync(refreshToken); + if (matchedToken == null) return Forbid(); + + // Rotate refresh token + matchedToken.Revoked = true; + var newRefreshToken = authService.GenerateRefreshToken(); + var hashedNewToken = BCrypt.Net.BCrypt.HashPassword(newRefreshToken); + + var newRefreshEntity = new RefreshToken + { + UserId = matchedToken.UserId, + Token = hashedNewToken, + ExpiryDate = DateTime.UtcNow.AddHours(configuration.GetValue("Jwt:RefreshTokenExpiryInHours", 24)), + JwtId = Guid.NewGuid().ToString(), + DeviceInfo = matchedToken.DeviceInfo, + ReplacedByToken = matchedToken.Token + }; + + await authService.SaveRefreshToken(newRefreshEntity); + + // Update cookie + SetRefreshTokenCookie(newRefreshToken); + + var newAccessToken = authService.GenerateAccessToken(matchedToken.User.Email); + return Ok(new { accessToken = newAccessToken }); + } + + [HttpPost("logout")] + public async Task Logout() + { + // Remove refresh token cookie + if (Request.Cookies.TryGetValue("refreshToken", out var incoming)) + { + await authService.RemoveRefreshToken(incoming); + } + + Response.Cookies.Delete("refreshToken", new CookieOptions + { + HttpOnly = true, + Secure = true, + SameSite = SameSiteMode.None, + Expires = DateTime.UtcNow.AddDays(-1) + }); + + return Ok(new { message = "Logged out successfully" }); + } + + + private void SetRefreshTokenCookie(string refreshToken) + { + var cookieOptions = new CookieOptions + { + HttpOnly = true, // JS cannot access + Secure = true, // HTTPS only + SameSite = SameSiteMode.None, // Prevent CSRF + Expires = DateTime.UtcNow.AddDays(7) + }; + + Response.Cookies.Append("refreshToken", refreshToken, cookieOptions); + } + } +} \ No newline at end of file diff --git a/PortBlog.API/Controllers/BlogController.cs b/PortBlog.API/Controllers/BlogController.cs index 7141e0a..ecc4ef5 100644 --- a/PortBlog.API/Controllers/BlogController.cs +++ b/PortBlog.API/Controllers/BlogController.cs @@ -1,6 +1,5 @@ using Asp.Versioning; using AutoMapper; -using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using PortBlog.API.Entities; using PortBlog.API.Models; diff --git a/PortBlog.API/Controllers/CvController.cs b/PortBlog.API/Controllers/CvController.cs index 9749ba2..da59e1d 100644 --- a/PortBlog.API/Controllers/CvController.cs +++ b/PortBlog.API/Controllers/CvController.cs @@ -1,8 +1,6 @@ using Asp.Versioning; using AutoMapper; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using PortBlog.API.Entities; using PortBlog.API.Models; using PortBlog.API.Repositories.Contracts; using PortBlog.API.Services.Contracts; @@ -257,7 +255,7 @@ namespace PortBlog.API.Controllers var candidateDto = _mapper.Map(candidate); var messageSendDto = _mapper.Map(message); messageSendDto.ToEmail = candidateDto.Email; - messageSendDto.CandidateName = candidateDto.DisplayName; + messageSendDto.Name = candidateDto.DisplayName; messageSendDto.CandidateId = candidateDto.CandidateId; await _mailService.SendAsync(messageSendDto); return Ok(true); diff --git a/PortBlog.API/DbContexts/CvBlogContext.cs b/PortBlog.API/DbContexts/CvBlogContext.cs index eb48fed..537c3eb 100644 --- a/PortBlog.API/DbContexts/CvBlogContext.cs +++ b/PortBlog.API/DbContexts/CvBlogContext.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using PortBlog.API.DbContexts.Seed; using PortBlog.API.Entities; +using PortBlog.API.Entities.Mapping; namespace PortBlog.API.DbContexts { @@ -37,6 +38,12 @@ namespace PortBlog.API.DbContexts public DbSet ClientLogs { get; set; } + public DbSet Cache { get; set; } + + public DbSet RefreshTokens { get; set; } + + public DbSet Users { get; set; } + protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().HasData(InitialData.GetCandidateData()); @@ -50,6 +57,8 @@ namespace PortBlog.API.DbContexts modelBuilder.Entity().HasData(InitialData.GetPostsData()); modelBuilder.Entity().HasData(InitialData.GetExperiencesData()); modelBuilder.Entity().HasData(InitialData.GetExperienceDetailsData()); + modelBuilder.Entity().HasData(InitialData.GetUsers()); + modelBuilder.ApplyConfiguration(new CacheMapping()); base.OnModelCreating(modelBuilder); } diff --git a/PortBlog.API/DbContexts/Seed/InitialData.cs b/PortBlog.API/DbContexts/Seed/InitialData.cs index 70e3b22..acdf829 100644 --- a/PortBlog.API/DbContexts/Seed/InitialData.cs +++ b/PortBlog.API/DbContexts/Seed/InitialData.cs @@ -1,5 +1,4 @@ using PortBlog.API.Entities; -using System.Net.NetworkInformation; namespace PortBlog.API.DbContexts.Seed { @@ -373,5 +372,18 @@ namespace PortBlog.API.DbContexts.Seed }; } + + public static List GetUsers() + { + return new List + { + new User + { + UserId = 1, + Username = "rajukottedi", + Email = "bangararaju.kottedi@gmail.com", + } + }; + } } } diff --git a/PortBlog.API/Entities/Cache.cs b/PortBlog.API/Entities/Cache.cs new file mode 100644 index 0000000..b39ffda --- /dev/null +++ b/PortBlog.API/Entities/Cache.cs @@ -0,0 +1,11 @@ +namespace PortBlog.API.Entities +{ + public class Cache + { + public string Id { get; set; } = null!; + public byte[] Value { get; set; } = null!; + public DateTime ExpiresAtTime { get; set; } + public long? SlidingExpirationInSeconds { get; set; } + public DateTime? AbsoluteExpiration { get; set; } + } +} diff --git a/PortBlog.API/Entities/Mapping/CacheMapping.cs b/PortBlog.API/Entities/Mapping/CacheMapping.cs new file mode 100644 index 0000000..955cbb1 --- /dev/null +++ b/PortBlog.API/Entities/Mapping/CacheMapping.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace PortBlog.API.Entities.Mapping +{ + public class CacheMapping : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(c => c.Id); + builder.Property(c => c.Id).ValueGeneratedOnAdd(); + builder.Property(c => c.ExpiresAtTime).IsRequired(); + builder.Property(c => c.Id).HasMaxLength(449).IsRequired(); + builder.Property(c => c.Value).IsRequired(); + } + } +} diff --git a/PortBlog.API/Entities/Message.cs b/PortBlog.API/Entities/Message.cs index 1b8dc6e..919386d 100644 --- a/PortBlog.API/Entities/Message.cs +++ b/PortBlog.API/Entities/Message.cs @@ -28,7 +28,6 @@ namespace PortBlog.API.Entities public string Subject { get; set; } = string.Empty; [Required] - [MaxLength(500)] public string Content { get; set; } = string.Empty; public int SentStatus { get; set; } = 0; diff --git a/PortBlog.API/Entities/RefreshToken.cs b/PortBlog.API/Entities/RefreshToken.cs new file mode 100644 index 0000000..6f65fcc --- /dev/null +++ b/PortBlog.API/Entities/RefreshToken.cs @@ -0,0 +1,33 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace PortBlog.API.Entities +{ + public class RefreshToken + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int TokenId { get; set; } + + [Required] + public int UserId { get; set; } + + [Required] + public string Token { get; set; } + + [Required] + public string JwtId { get; set; } + + [Required] + public DateTime ExpiryDate { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public bool Revoked { get; set; } = false; + public string? ReplacedByToken { get; set; } + + [Required] + public string DeviceInfo { get; set; } + + [ForeignKey(nameof(UserId))] + public User User { get; set; } + } +} diff --git a/PortBlog.API/Entities/User.cs b/PortBlog.API/Entities/User.cs new file mode 100644 index 0000000..72f9b84 --- /dev/null +++ b/PortBlog.API/Entities/User.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; + +namespace PortBlog.API.Entities +{ + public class User + { + [Key] + public int UserId { get; set; } + + [Required] + public string Username { get; set; } + + [Required] + public string Email { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + + public ICollection RefreshTokens { get; set; } + } +} diff --git a/PortBlog.API/Extensions/ServiceExtensions.cs b/PortBlog.API/Extensions/ServiceExtensions.cs index 68d4e5f..39b1282 100644 --- a/PortBlog.API/Extensions/ServiceExtensions.cs +++ b/PortBlog.API/Extensions/ServiceExtensions.cs @@ -19,6 +19,8 @@ namespace PortBlog.API.Extensions public static IServiceCollection AddServices(this IServiceCollection services) { services.AddTransient(); + services.AddTransient(); + services.AddTransient(); return services; } } diff --git a/PortBlog.API/Migrations/20251001130551_CreateCacheTable.Designer.cs b/PortBlog.API/Migrations/20251001130551_CreateCacheTable.Designer.cs new file mode 100644 index 0000000..c8e4145 --- /dev/null +++ b/PortBlog.API/Migrations/20251001130551_CreateCacheTable.Designer.cs @@ -0,0 +1,1393 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PortBlog.API.DbContexts; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + [DbContext(typeof(CvBlogContext))] + [Migration("20251001130551_CreateCacheTable")] + partial class CreateCacheTable + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.Property("AcademicId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("AcademicId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Degree") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("DegreeSpecialization") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("EndYear") + .HasColumnType("int"); + + b.Property("Institution") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartYear") + .HasColumnType("int"); + + b.HasKey("AcademicId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Academics"); + + b.HasData( + new + { + AcademicId = 1, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7668), + Degree = "High School", + EndYear = 2007, + Institution = "Pragati Little Public School", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7668), + ResumeId = 1, + StartYear = 2006 + }, + new + { + AcademicId = 2, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7674), + Degree = "Intermediate", + DegreeSpecialization = "MPC", + EndYear = 2009, + Institution = "Sri Chaitanya Junior College", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7674), + ResumeId = 1, + StartYear = 2007 + }, + new + { + AcademicId = 3, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7677), + Degree = "BTech", + DegreeSpecialization = "ECE", + EndYear = 2013, + Institution = "Kakinada Institute of Technology & Science", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7677), + ResumeId = 1, + StartYear = 2009 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.HasKey("BlogUrl"); + + b.ToTable("Blogs"); + + b.HasData( + new + { + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7790), + Description = "Your Hub for Tech, DIY, and Innovation", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7791), + Name = "Engineer's Odyssey" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Cache", b => + { + b.Property("Id") + .HasMaxLength(449) + .HasColumnType("varchar(449)"); + + b.Property("AbsoluteExpiration") + .HasColumnType("datetime(6)"); + + b.Property("ExpiresAtTime") + .HasColumnType("datetime(6)"); + + b.Property("SlidingExpirationInSeconds") + .HasColumnType("bigint"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longblob"); + + b.HasKey("Id"); + + b.ToTable("Cache"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Property("CandidateId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CandidateId")); + + b.Property("Address") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Avatar") + .HasColumnType("longtext"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Dob") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.HasKey("CandidateId"); + + b.ToTable("Candidates"); + + b.HasData( + new + { + CandidateId = 1, + Address = "Samalkot, Andhra Pradesh, India", + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7275), + Dob = new DateTime(1992, 5, 6, 0, 0, 0, 0, DateTimeKind.Unspecified), + Email = "bangararaju.kottedi@gmail.com", + FirstName = "Bangara Raju", + Gender = "Male", + LastName = "Kottedi", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7304), + Phone = "+91 9441212187" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.Property("CertificationId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CertificationId")); + + b.Property("CertificationLink") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CertificationName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("IssueDate") + .HasColumnType("datetime(6)"); + + b.Property("IssuingOrganization") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("CertificationId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Certifications"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ClientLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClientIp") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ClientLocation") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("SiteName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SiteUrl") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.ToTable("ClientLogs"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Property("ExperienceId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ExperienceId")); + + b.Property("Company") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ExperienceId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Experiences"); + + b.HasData( + new + { + ExperienceId = 1, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7903), + Description = "", + EndDate = new DateTime(2016, 4, 25, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7904), + ResumeId = 1, + StartDate = new DateTime(2015, 9, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Jr. Software Engineer" + }, + new + { + ExperienceId = 2, + Company = "Agility", + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7908), + Description = "", + EndDate = new DateTime(2022, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7909), + ResumeId = 1, + StartDate = new DateTime(2016, 5, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Web Developer" + }, + new + { + ExperienceId = 3, + Company = "Agility", + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7912), + Description = "", + EndDate = new DateTime(2022, 10, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7913), + ResumeId = 1, + StartDate = new DateTime(2022, 2, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Senior Web Developer" + }, + new + { + ExperienceId = 4, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7915), + Description = "", + EndDate = new DateTime(2024, 4, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7916), + ResumeId = 1, + StartDate = new DateTime(2022, 11, 4, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Technology Specialist" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("ExperienceId") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ExperienceId"); + + b.ToTable("ExperienceDetails"); + + b.HasData( + new + { + Id = 1, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7944), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7944), + Order = 1 + }, + new + { + Id = 2, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7948), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7949), + Order = 2 + }, + new + { + Id = 3, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7950), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7951), + Order = 1 + }, + new + { + Id = 4, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7952), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7953), + Order = 2 + }, + new + { + Id = 5, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7954), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7955), + Order = 1 + }, + new + { + Id = 6, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7957), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7957), + Order = 2 + }, + new + { + Id = 7, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7958), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7959), + Order = 1 + }, + new + { + Id = 8, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(8011), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(8011), + Order = 2 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.Property("HobbyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("HobbyId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("HobbyId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Hobbies"); + + b.HasData( + new + { + HobbyId = 1, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7625), + Description = "Crafting Professional-Quality Websites with Precision.", + Icon = "fa-square-terminal", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7625), + Name = "Web Development", + Order = 1, + ResumeId = 1 + }, + new + { + HobbyId = 2, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7633), + Description = "Streamlining and Simplifying Complex Tasks through Automation.", + Icon = "fa-robot", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7633), + Name = "Automation", + Order = 2, + ResumeId = 1 + }, + new + { + HobbyId = 3, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7635), + Description = "Sharing the knowledge and insights I’ve gathered along my journey.", + Icon = "fa-typewriter", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7636), + Name = "Blogging", + Order = 3, + ResumeId = 1 + }, + new + { + HobbyId = 4, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7638), + Description = "Exploring, embracing, and leveraging the latest advancements.", + Icon = "fa-lightbulb-gear", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7638), + Name = "Technology", + Order = 4, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FromEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SentStatus") + .HasColumnType("int"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ToEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("CandidateId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.Property("PostId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("PostId")); + + b.Property("Author") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("BlogUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Comments") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Image") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Likes") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PostUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("PostId"); + + b.HasIndex("BlogUrl"); + + b.ToTable("Posts"); + + b.HasData( + new + { + PostId = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7820), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7817), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 2, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7826), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7824), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 3, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7830), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7828), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.Property("ProjectId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ProjectId")); + + b.Property("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Challenges") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("ImagePath") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Impact") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("LessonsLearned") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Responsibilities") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Roles") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("TechnologiesUsed") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("ProjectId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Projects"); + + b.HasData( + new + { + ProjectId = 1, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7754), + Description = "Business Process Management", + ImagePath = "bpm.jpg", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7755), + Name = "Transfora (Business Process Management)", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 2, + Categories = "[\"Web Design\"]", + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7761), + Description = "Business Process Management", + ImagePath = "hcm.jpg", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7762), + Name = "Human Captial Management", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 3, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7765), + Description = "Business Process Management", + ImagePath = "hms.png", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7765), + Name = "Transfora (Business Process Management)", + Responsibilities = "Hosting, Integrating, Monitoring", + ResumeId = 1, + Roles = "Integration, Monitor", + TechnologiesUsed = ".NET, Angular" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Property("ResumeId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ResumeId")); + + b.Property("About") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("varchar(1000)"); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ResumeId"); + + b.HasIndex("CandidateId"); + + b.ToTable("Resumes"); + + b.HasData( + new + { + ResumeId = 1, + About = "I'm Full Stack Developer with 8+ years of hands-on experience in .NET development. Passionate and driven professional with expertise in .NET WebAPI, Angular, CI/CD, and a growing proficiency in Azure. I've successfully delivered robust applications, prioritizing efficiency and user experience. While I'm currently in the early stages of exploring Azure, I'm eager to expand my skill set and leverage cloud technologies to enhance scalability and performance. Known for my proactive approach and dedication to continuous learning, I'm committed to staying abreast of the latest technologies and methodologies to drive innovation and deliver exceptional results.", + CandidateId = 1, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7563), + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7564), + Order = 1, + Title = "Full Stack Developer" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.Property("FileId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("FileId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FileFormat") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Version") + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.HasKey("FileId"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.Property("SkillId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("SkillId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ProficiencyLevel") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("SkillId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Skills"); + + b.HasData( + new + { + SkillId = 1, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7705), + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7706), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 2, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7710), + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7711), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 3, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7712), + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7713), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 4, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7714), + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7715), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 5, + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7716), + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7717), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Facebook") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("GitHub") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Instagram") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Linkedin") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PersonalWebsite") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Twitter") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("BlogUrl"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("SocialLinks"); + + b.HasData( + new + { + Id = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7592), + GitHub = "https://github.com/rajukottedi", + Linkedin = "https://in.linkedin.com/in/bangara-raju-kottedi-299072109", + ModifiedDate = new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7593), + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Academics") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Certifications") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Experiences") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.HasOne("PortBlog.API.Entities.Experience", "Experience") + .WithMany("Details") + .HasForeignKey("ExperienceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Experience"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Hobbies") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany() + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany("Posts") + .HasForeignKey("BlogUrl") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Projects") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany("Resumes") + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("ResumeFile") + .HasForeignKey("PortBlog.API.Entities.ResumeFile", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Skills") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany() + .HasForeignKey("BlogUrl"); + + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("SocialLinks") + .HasForeignKey("PortBlog.API.Entities.SocialLinks", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Navigation("Posts"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Navigation("Resumes"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Navigation("Details"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Navigation("Academics"); + + b.Navigation("Certifications"); + + b.Navigation("Experiences"); + + b.Navigation("Hobbies"); + + b.Navigation("Projects"); + + b.Navigation("ResumeFile"); + + b.Navigation("Skills"); + + b.Navigation("SocialLinks"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PortBlog.API/Migrations/20251001130551_CreateCacheTable.cs b/PortBlog.API/Migrations/20251001130551_CreateCacheTable.cs new file mode 100644 index 0000000..0e7078e --- /dev/null +++ b/PortBlog.API/Migrations/20251001130551_CreateCacheTable.cs @@ -0,0 +1,515 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + /// + public partial class CreateCacheTable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Cache", + columns: table => new + { + Id = table.Column(type: "varchar(449)", maxLength: 449, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "longblob", nullable: false), + ExpiresAtTime = table.Column(type: "datetime(6)", nullable: false), + SlidingExpirationInSeconds = table.Column(type: "bigint", nullable: true), + AbsoluteExpiration = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Cache", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7668), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7668) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7674), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7674) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7677), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7677) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7790), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7791) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7275), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7304) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7944), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7944) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7948), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7949) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7950), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7951) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7952), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7953) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7954), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7955) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7957), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7957) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7958), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7959) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(8011), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(8011) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7903), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7904) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7908), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7909) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7912), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7913) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7915), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7916) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7625), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7625) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7633), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7633) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7635), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7636) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7638), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7638) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7820), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7817) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7826), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7824) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7830), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7828) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7754), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7755) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7761), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7762) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7765), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7765) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7563), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7564) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7705), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7706) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7710), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7711) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7712), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7713) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7714), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7715) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7716), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7717) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7592), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7593) }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Cache"); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8945), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8945) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8948), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8949) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8950), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8951) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9023), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9023) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8726), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8742) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9096), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9096) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9099), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9100) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9101), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9101) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9102), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9102) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9103), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9103) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9105), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9105) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9106), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9106) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9107), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9108) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9068), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9068) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9072), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9073) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9075), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9075) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9077), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9077) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8912), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8913) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8917), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8918) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8919), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8919) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8921), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8921) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9042), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9038) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9047), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9045) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9049), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9048) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8997), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8997) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9003), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9003) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9006), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9006) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8874), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8874) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8968), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8968) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8971), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8972) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8973), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8973) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8974), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8974) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8975), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8976) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8894), new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8895) }); + } + } +} diff --git a/PortBlog.API/Migrations/20251008082117_MessageContentMaxLength.Designer.cs b/PortBlog.API/Migrations/20251008082117_MessageContentMaxLength.Designer.cs new file mode 100644 index 0000000..d7a4cf8 --- /dev/null +++ b/PortBlog.API/Migrations/20251008082117_MessageContentMaxLength.Designer.cs @@ -0,0 +1,1392 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PortBlog.API.DbContexts; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + [DbContext(typeof(CvBlogContext))] + [Migration("20251008082117_MessageContentMaxLength")] + partial class MessageContentMaxLength + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.Property("AcademicId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("AcademicId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Degree") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("DegreeSpecialization") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("EndYear") + .HasColumnType("int"); + + b.Property("Institution") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartYear") + .HasColumnType("int"); + + b.HasKey("AcademicId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Academics"); + + b.HasData( + new + { + AcademicId = 1, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(5183), + Degree = "High School", + EndYear = 2007, + Institution = "Pragati Little Public School", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(5185), + ResumeId = 1, + StartYear = 2006 + }, + new + { + AcademicId = 2, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6375), + Degree = "Intermediate", + DegreeSpecialization = "MPC", + EndYear = 2009, + Institution = "Sri Chaitanya Junior College", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6376), + ResumeId = 1, + StartYear = 2007 + }, + new + { + AcademicId = 3, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6564), + Degree = "BTech", + DegreeSpecialization = "ECE", + EndYear = 2013, + Institution = "Kakinada Institute of Technology & Science", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6565), + ResumeId = 1, + StartYear = 2009 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.HasKey("BlogUrl"); + + b.ToTable("Blogs"); + + b.HasData( + new + { + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(8487), + Description = "Your Hub for Tech, DIY, and Innovation", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(8489), + Name = "Engineer's Odyssey" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Cache", b => + { + b.Property("Id") + .HasMaxLength(449) + .HasColumnType("varchar(449)"); + + b.Property("AbsoluteExpiration") + .HasColumnType("datetime(6)"); + + b.Property("ExpiresAtTime") + .HasColumnType("datetime(6)"); + + b.Property("SlidingExpirationInSeconds") + .HasColumnType("bigint"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longblob"); + + b.HasKey("Id"); + + b.ToTable("Cache"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Property("CandidateId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CandidateId")); + + b.Property("Address") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Avatar") + .HasColumnType("longtext"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Dob") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.HasKey("CandidateId"); + + b.ToTable("Candidates"); + + b.HasData( + new + { + CandidateId = 1, + Address = "Samalkot, Andhra Pradesh, India", + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 890, DateTimeKind.Local).AddTicks(2043), + Dob = new DateTime(1992, 5, 6, 0, 0, 0, 0, DateTimeKind.Unspecified), + Email = "bangararaju.kottedi@gmail.com", + FirstName = "Bangara Raju", + Gender = "Male", + LastName = "Kottedi", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 890, DateTimeKind.Local).AddTicks(2090), + Phone = "+91 9441212187" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.Property("CertificationId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CertificationId")); + + b.Property("CertificationLink") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CertificationName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("IssueDate") + .HasColumnType("datetime(6)"); + + b.Property("IssuingOrganization") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("CertificationId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Certifications"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ClientLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClientIp") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ClientLocation") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("SiteName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SiteUrl") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.ToTable("ClientLogs"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Property("ExperienceId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ExperienceId")); + + b.Property("Company") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ExperienceId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Experiences"); + + b.HasData( + new + { + ExperienceId = 1, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(2643), + Description = "", + EndDate = new DateTime(2016, 4, 25, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(2652), + ResumeId = 1, + StartDate = new DateTime(2015, 9, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Jr. Software Engineer" + }, + new + { + ExperienceId = 2, + Company = "Agility", + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4851), + Description = "", + EndDate = new DateTime(2022, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4852), + ResumeId = 1, + StartDate = new DateTime(2016, 5, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Web Developer" + }, + new + { + ExperienceId = 3, + Company = "Agility", + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4859), + Description = "", + EndDate = new DateTime(2022, 10, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4861), + ResumeId = 1, + StartDate = new DateTime(2022, 2, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Senior Web Developer" + }, + new + { + ExperienceId = 4, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4866), + Description = "", + EndDate = new DateTime(2024, 4, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4867), + ResumeId = 1, + StartDate = new DateTime(2022, 11, 4, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Technology Specialist" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("ExperienceId") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ExperienceId"); + + b.ToTable("ExperienceDetails"); + + b.HasData( + new + { + Id = 1, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(9986), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(9994), + Order = 1 + }, + new + { + Id = 2, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(902), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(903), + Order = 2 + }, + new + { + Id = 3, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(908), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(909), + Order = 1 + }, + new + { + Id = 4, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(912), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(913), + Order = 2 + }, + new + { + Id = 5, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(916), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(917), + Order = 1 + }, + new + { + Id = 6, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(931), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(932), + Order = 2 + }, + new + { + Id = 7, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(936), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(937), + Order = 1 + }, + new + { + Id = 8, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(940), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(941), + Order = 2 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.Property("HobbyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("HobbyId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("HobbyId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Hobbies"); + + b.HasData( + new + { + HobbyId = 1, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(447), + Description = "Crafting Professional-Quality Websites with Precision.", + Icon = "fa-square-terminal", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(450), + Name = "Web Development", + Order = 1, + ResumeId = 1 + }, + new + { + HobbyId = 2, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1567), + Description = "Streamlining and Simplifying Complex Tasks through Automation.", + Icon = "fa-robot", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1568), + Name = "Automation", + Order = 2, + ResumeId = 1 + }, + new + { + HobbyId = 3, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1680), + Description = "Sharing the knowledge and insights I’ve gathered along my journey.", + Icon = "fa-typewriter", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1681), + Name = "Blogging", + Order = 3, + ResumeId = 1 + }, + new + { + HobbyId = 4, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1686), + Description = "Exploring, embracing, and leveraging the latest advancements.", + Icon = "fa-lightbulb-gear", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1686), + Name = "Technology", + Order = 4, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FromEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SentStatus") + .HasColumnType("int"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ToEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("CandidateId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.Property("PostId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("PostId")); + + b.Property("Author") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("BlogUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.PrimitiveCollection("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Comments") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Image") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Likes") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PostUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("PostId"); + + b.HasIndex("BlogUrl"); + + b.ToTable("Posts"); + + b.HasData( + new + { + PostId = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(4722), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(3517), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 2, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5740), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5735), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 3, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5747), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5744), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.Property("ProjectId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ProjectId")); + + b.PrimitiveCollection("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Challenges") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("ImagePath") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Impact") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("LessonsLearned") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Responsibilities") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Roles") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("TechnologiesUsed") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("ProjectId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Projects"); + + b.HasData( + new + { + ProjectId = 1, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(4258), + Description = "Business Process Management", + ImagePath = "bpm.jpg", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(4259), + Name = "Transfora (Business Process Management)", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 2, + Categories = "[\"Web Design\"]", + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6406), + Description = "Business Process Management", + ImagePath = "hcm.jpg", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6411), + Name = "Human Captial Management", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 3, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6419), + Description = "Business Process Management", + ImagePath = "hms.png", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6420), + Name = "Transfora (Business Process Management)", + Responsibilities = "Hosting, Integrating, Monitoring", + ResumeId = 1, + Roles = "Integration, Monitor", + TechnologiesUsed = ".NET, Angular" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Property("ResumeId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ResumeId")); + + b.Property("About") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("varchar(1000)"); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ResumeId"); + + b.HasIndex("CandidateId"); + + b.ToTable("Resumes"); + + b.HasData( + new + { + ResumeId = 1, + About = "I'm Full Stack Developer with 8+ years of hands-on experience in .NET development. Passionate and driven professional with expertise in .NET WebAPI, Angular, CI/CD, and a growing proficiency in Azure. I've successfully delivered robust applications, prioritizing efficiency and user experience. While I'm currently in the early stages of exploring Azure, I'm eager to expand my skill set and leverage cloud technologies to enhance scalability and performance. Known for my proactive approach and dedication to continuous learning, I'm committed to staying abreast of the latest technologies and methodologies to drive innovation and deliver exceptional results.", + CandidateId = 1, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(2802), + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(2819), + Order = 1, + Title = "Full Stack Developer" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.Property("FileId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("FileId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FileFormat") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Version") + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.HasKey("FileId"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.Property("SkillId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("SkillId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ProficiencyLevel") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("SkillId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Skills"); + + b.HasData( + new + { + SkillId = 1, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(9417), + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(9419), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 2, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(241), + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(242), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 3, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(246), + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(246), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 4, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(249), + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(250), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 5, + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(253), + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(254), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Facebook") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("GitHub") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Instagram") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Linkedin") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PersonalWebsite") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Twitter") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("BlogUrl"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("SocialLinks"); + + b.HasData( + new + { + Id = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(6490), + GitHub = "https://github.com/rajukottedi", + Linkedin = "https://in.linkedin.com/in/bangara-raju-kottedi-299072109", + ModifiedDate = new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(6498), + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Academics") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Certifications") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Experiences") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.HasOne("PortBlog.API.Entities.Experience", "Experience") + .WithMany("Details") + .HasForeignKey("ExperienceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Experience"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Hobbies") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany() + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany("Posts") + .HasForeignKey("BlogUrl") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Projects") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany("Resumes") + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("ResumeFile") + .HasForeignKey("PortBlog.API.Entities.ResumeFile", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Skills") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany() + .HasForeignKey("BlogUrl"); + + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("SocialLinks") + .HasForeignKey("PortBlog.API.Entities.SocialLinks", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Navigation("Posts"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Navigation("Resumes"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Navigation("Details"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Navigation("Academics"); + + b.Navigation("Certifications"); + + b.Navigation("Experiences"); + + b.Navigation("Hobbies"); + + b.Navigation("Projects"); + + b.Navigation("ResumeFile"); + + b.Navigation("Skills"); + + b.Navigation("SocialLinks"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PortBlog.API/Migrations/20251008082117_MessageContentMaxLength.cs b/PortBlog.API/Migrations/20251008082117_MessageContentMaxLength.cs new file mode 100644 index 0000000..cb47537 --- /dev/null +++ b/PortBlog.API/Migrations/20251008082117_MessageContentMaxLength.cs @@ -0,0 +1,517 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + /// + public partial class MessageContentMaxLength : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Content", + table: "Messages", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(500)", + oldMaxLength: 500) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(5183), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(5185) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6375), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6376) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6564), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6565) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(8487), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(8489) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 890, DateTimeKind.Local).AddTicks(2043), new DateTime(2025, 10, 8, 13, 51, 15, 890, DateTimeKind.Local).AddTicks(2090) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(9986), new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(9994) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(902), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(903) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(908), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(909) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(912), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(913) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(916), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(917) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(931), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(932) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(936), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(937) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(940), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(941) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(2643), new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(2652) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4851), new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4852) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4859), new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4861) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4866), new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4867) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(447), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(450) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1567), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1568) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1680), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1681) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1686), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1686) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(4722), new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(3517) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5740), new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5735) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5747), new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5744) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(4258), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(4259) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6406), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6411) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6419), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6420) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(2802), new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(2819) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(9417), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(9419) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(241), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(242) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(246), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(246) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(249), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(250) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(253), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(254) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(6490), new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(6498) }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Content", + table: "Messages", + type: "varchar(500)", + maxLength: 500, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7668), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7668) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7674), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7674) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7677), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7677) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7790), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7791) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7275), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7304) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7944), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7944) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7948), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7949) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7950), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7951) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7952), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7953) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7954), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7955) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7957), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7957) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7958), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7959) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(8011), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(8011) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7903), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7904) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7908), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7909) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7912), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7913) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7915), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7916) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7625), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7625) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7633), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7633) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7635), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7636) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7638), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7638) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7820), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7817) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7826), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7824) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7830), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7828) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7754), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7755) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7761), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7762) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7765), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7765) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7563), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7564) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7705), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7706) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7710), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7711) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7712), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7713) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7714), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7715) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7716), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7717) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7592), new DateTime(2025, 10, 1, 18, 35, 50, 567, DateTimeKind.Local).AddTicks(7593) }); + } + } +} diff --git a/PortBlog.API/Migrations/20251028060442_User_RefreshTokens.Designer.cs b/PortBlog.API/Migrations/20251028060442_User_RefreshTokens.Designer.cs new file mode 100644 index 0000000..06d451b --- /dev/null +++ b/PortBlog.API/Migrations/20251028060442_User_RefreshTokens.Designer.cs @@ -0,0 +1,1392 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PortBlog.API.DbContexts; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + [DbContext(typeof(CvBlogContext))] + [Migration("20251028060442_User_RefreshTokens")] + partial class User_RefreshTokens + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.Property("AcademicId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("AcademicId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Degree") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("DegreeSpecialization") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("EndYear") + .HasColumnType("int"); + + b.Property("Institution") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartYear") + .HasColumnType("int"); + + b.HasKey("AcademicId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Academics"); + + b.HasData( + new + { + AcademicId = 1, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(4652), + Degree = "High School", + EndYear = 2007, + Institution = "Pragati Little Public School", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(4653), + ResumeId = 1, + StartYear = 2006 + }, + new + { + AcademicId = 2, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5447), + Degree = "Intermediate", + DegreeSpecialization = "MPC", + EndYear = 2009, + Institution = "Sri Chaitanya Junior College", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5448), + ResumeId = 1, + StartYear = 2007 + }, + new + { + AcademicId = 3, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5558), + Degree = "BTech", + DegreeSpecialization = "ECE", + EndYear = 2013, + Institution = "Kakinada Institute of Technology & Science", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5559), + ResumeId = 1, + StartYear = 2009 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.HasKey("BlogUrl"); + + b.ToTable("Blogs"); + + b.HasData( + new + { + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(3195), + Description = "Your Hub for Tech, DIY, and Innovation", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(3196), + Name = "Engineer's Odyssey" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Cache", b => + { + b.Property("Id") + .HasMaxLength(449) + .HasColumnType("varchar(449)"); + + b.Property("AbsoluteExpiration") + .HasColumnType("datetime(6)"); + + b.Property("ExpiresAtTime") + .HasColumnType("datetime(6)"); + + b.Property("SlidingExpirationInSeconds") + .HasColumnType("bigint"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longblob"); + + b.HasKey("Id"); + + b.ToTable("Cache"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Property("CandidateId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CandidateId")); + + b.Property("Address") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Avatar") + .HasColumnType("longtext"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Dob") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.HasKey("CandidateId"); + + b.ToTable("Candidates"); + + b.HasData( + new + { + CandidateId = 1, + Address = "Samalkot, Andhra Pradesh, India", + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 690, DateTimeKind.Local).AddTicks(9239), + Dob = new DateTime(1992, 5, 6, 0, 0, 0, 0, DateTimeKind.Unspecified), + Email = "bangararaju.kottedi@gmail.com", + FirstName = "Bangara Raju", + Gender = "Male", + LastName = "Kottedi", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 690, DateTimeKind.Local).AddTicks(9275), + Phone = "+91 9441212187" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.Property("CertificationId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CertificationId")); + + b.Property("CertificationLink") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CertificationName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("IssueDate") + .HasColumnType("datetime(6)"); + + b.Property("IssuingOrganization") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("CertificationId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Certifications"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ClientLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClientIp") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ClientLocation") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("SiteName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SiteUrl") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.ToTable("ClientLogs"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Property("ExperienceId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ExperienceId")); + + b.Property("Company") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ExperienceId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Experiences"); + + b.HasData( + new + { + ExperienceId = 1, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(375), + Description = "", + EndDate = new DateTime(2016, 4, 25, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(377), + ResumeId = 1, + StartDate = new DateTime(2015, 9, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Jr. Software Engineer" + }, + new + { + ExperienceId = 2, + Company = "Agility", + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1466), + Description = "", + EndDate = new DateTime(2022, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1467), + ResumeId = 1, + StartDate = new DateTime(2016, 5, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Web Developer" + }, + new + { + ExperienceId = 3, + Company = "Agility", + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1471), + Description = "", + EndDate = new DateTime(2022, 10, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1472), + ResumeId = 1, + StartDate = new DateTime(2022, 2, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Senior Web Developer" + }, + new + { + ExperienceId = 4, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1475), + Description = "", + EndDate = new DateTime(2024, 4, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1475), + ResumeId = 1, + StartDate = new DateTime(2022, 11, 4, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Technology Specialist" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("ExperienceId") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ExperienceId"); + + b.ToTable("ExperienceDetails"); + + b.HasData( + new + { + Id = 1, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(3656), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(3657), + Order = 1 + }, + new + { + Id = 2, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4150), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4150), + Order = 2 + }, + new + { + Id = 3, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4152), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4153), + Order = 1 + }, + new + { + Id = 4, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4154), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4155), + Order = 2 + }, + new + { + Id = 5, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4156), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4156), + Order = 1 + }, + new + { + Id = 6, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4161), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4161), + Order = 2 + }, + new + { + Id = 7, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4163), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4163), + Order = 1 + }, + new + { + Id = 8, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4164), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4165), + Order = 2 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.Property("HobbyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("HobbyId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("HobbyId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Hobbies"); + + b.HasData( + new + { + HobbyId = 1, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2045), + Description = "Crafting Professional-Quality Websites with Precision.", + Icon = "fa-square-terminal", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2046), + Name = "Web Development", + Order = 1, + ResumeId = 1 + }, + new + { + HobbyId = 2, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2725), + Description = "Streamlining and Simplifying Complex Tasks through Automation.", + Icon = "fa-robot", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2725), + Name = "Automation", + Order = 2, + ResumeId = 1 + }, + new + { + HobbyId = 3, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2728), + Description = "Sharing the knowledge and insights I’ve gathered along my journey.", + Icon = "fa-typewriter", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2729), + Name = "Blogging", + Order = 3, + ResumeId = 1 + }, + new + { + HobbyId = 4, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2730), + Description = "Exploring, embracing, and leveraging the latest advancements.", + Icon = "fa-lightbulb-gear", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2731), + Name = "Technology", + Order = 4, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FromEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SentStatus") + .HasColumnType("int"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ToEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("CandidateId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.Property("PostId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("PostId")); + + b.Property("Author") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("BlogUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.PrimitiveCollection("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Comments") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Image") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Likes") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PostUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("PostId"); + + b.HasIndex("BlogUrl"); + + b.ToTable("Posts"); + + b.HasData( + new + { + PostId = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7094), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(6266), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 2, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7426), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7423), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 3, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7429), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7428), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.Property("ProjectId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ProjectId")); + + b.PrimitiveCollection("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Challenges") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("ImagePath") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Impact") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("LessonsLearned") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Responsibilities") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Roles") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("TechnologiesUsed") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("ProjectId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Projects"); + + b.HasData( + new + { + ProjectId = 1, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(911), + Description = "Business Process Management", + ImagePath = "bpm.jpg", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(912), + Name = "Transfora (Business Process Management)", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 2, + Categories = "[\"Web Design\"]", + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2038), + Description = "Business Process Management", + ImagePath = "hcm.jpg", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2039), + Name = "Human Captial Management", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 3, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2042), + Description = "Business Process Management", + ImagePath = "hms.png", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2043), + Name = "Transfora (Business Process Management)", + Responsibilities = "Hosting, Integrating, Monitoring", + ResumeId = 1, + Roles = "Integration, Monitor", + TechnologiesUsed = ".NET, Angular" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Property("ResumeId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ResumeId")); + + b.Property("About") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("varchar(1000)"); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ResumeId"); + + b.HasIndex("CandidateId"); + + b.ToTable("Resumes"); + + b.HasData( + new + { + ResumeId = 1, + About = "I'm Full Stack Developer with 8+ years of hands-on experience in .NET development. Passionate and driven professional with expertise in .NET WebAPI, Angular, CI/CD, and a growing proficiency in Azure. I've successfully delivered robust applications, prioritizing efficiency and user experience. While I'm currently in the early stages of exploring Azure, I'm eager to expand my skill set and leverage cloud technologies to enhance scalability and performance. Known for my proactive approach and dedication to continuous learning, I'm committed to staying abreast of the latest technologies and methodologies to drive innovation and deliver exceptional results.", + CandidateId = 1, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(7935), + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(7944), + Order = 1, + Title = "Full Stack Developer" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.Property("FileId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("FileId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FileFormat") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Version") + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.HasKey("FileId"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.Property("SkillId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("SkillId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ProficiencyLevel") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("SkillId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Skills"); + + b.HasData( + new + { + SkillId = 1, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(7751), + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(7757), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 2, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8313), + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8314), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 3, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8316), + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8317), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 4, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8318), + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8318), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 5, + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8320), + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8320), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Facebook") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("GitHub") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Instagram") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Linkedin") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PersonalWebsite") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Twitter") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("BlogUrl"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("SocialLinks"); + + b.HasData( + new + { + Id = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(9726), + GitHub = "https://github.com/rajukottedi", + Linkedin = "https://in.linkedin.com/in/bangara-raju-kottedi-299072109", + ModifiedDate = new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(9728), + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Academics") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Certifications") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Experiences") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.HasOne("PortBlog.API.Entities.Experience", "Experience") + .WithMany("Details") + .HasForeignKey("ExperienceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Experience"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Hobbies") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany() + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany("Posts") + .HasForeignKey("BlogUrl") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Projects") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany("Resumes") + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("ResumeFile") + .HasForeignKey("PortBlog.API.Entities.ResumeFile", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Skills") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany() + .HasForeignKey("BlogUrl"); + + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("SocialLinks") + .HasForeignKey("PortBlog.API.Entities.SocialLinks", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Navigation("Posts"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Navigation("Resumes"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Navigation("Details"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Navigation("Academics"); + + b.Navigation("Certifications"); + + b.Navigation("Experiences"); + + b.Navigation("Hobbies"); + + b.Navigation("Projects"); + + b.Navigation("ResumeFile"); + + b.Navigation("Skills"); + + b.Navigation("SocialLinks"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PortBlog.API/Migrations/20251028060442_User_RefreshTokens.cs b/PortBlog.API/Migrations/20251028060442_User_RefreshTokens.cs new file mode 100644 index 0000000..f362c51 --- /dev/null +++ b/PortBlog.API/Migrations/20251028060442_User_RefreshTokens.cs @@ -0,0 +1,495 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + /// + public partial class User_RefreshTokens : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(4652), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(4653) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5447), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5448) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5558), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5559) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(3195), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(3196) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 690, DateTimeKind.Local).AddTicks(9239), new DateTime(2025, 10, 28, 11, 34, 41, 690, DateTimeKind.Local).AddTicks(9275) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(3656), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(3657) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4150), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4150) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4152), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4153) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4154), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4155) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4156), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4156) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4161), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4161) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4163), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4163) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4164), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4165) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(375), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(377) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1466), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1467) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1471), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1472) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1475), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1475) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2045), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2046) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2725), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2725) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2728), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2729) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2730), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2731) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7094), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(6266) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7426), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7423) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7429), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7428) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(911), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(912) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2038), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2039) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2042), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2043) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(7935), new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(7944) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(7751), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(7757) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8313), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8314) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8316), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8317) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8318), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8318) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8320), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8320) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(9726), new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(9728) }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(5183), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(5185) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6375), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6376) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6564), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(6565) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(8487), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(8489) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 890, DateTimeKind.Local).AddTicks(2043), new DateTime(2025, 10, 8, 13, 51, 15, 890, DateTimeKind.Local).AddTicks(2090) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(9986), new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(9994) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(902), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(903) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(908), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(909) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(912), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(913) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(916), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(917) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(931), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(932) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(936), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(937) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(940), new DateTime(2025, 10, 8, 13, 51, 15, 897, DateTimeKind.Local).AddTicks(941) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(2643), new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(2652) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4851), new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4852) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4859), new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4861) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4866), new DateTime(2025, 10, 8, 13, 51, 15, 896, DateTimeKind.Local).AddTicks(4867) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(447), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(450) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1567), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1568) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1680), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1681) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1686), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(1686) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(4722), new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(3517) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5740), new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5735) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5747), new DateTime(2025, 10, 8, 13, 51, 15, 895, DateTimeKind.Local).AddTicks(5744) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(4258), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(4259) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6406), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6411) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6419), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(6420) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(2802), new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(2819) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(9417), new DateTime(2025, 10, 8, 13, 51, 15, 893, DateTimeKind.Local).AddTicks(9419) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(241), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(242) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(246), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(246) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(249), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(250) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(253), new DateTime(2025, 10, 8, 13, 51, 15, 894, DateTimeKind.Local).AddTicks(254) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(6490), new DateTime(2025, 10, 8, 13, 51, 15, 892, DateTimeKind.Local).AddTicks(6498) }); + } + } +} diff --git a/PortBlog.API/Migrations/20251028062356_User_RefreshTokens_Rerun.Designer.cs b/PortBlog.API/Migrations/20251028062356_User_RefreshTokens_Rerun.Designer.cs new file mode 100644 index 0000000..f069494 --- /dev/null +++ b/PortBlog.API/Migrations/20251028062356_User_RefreshTokens_Rerun.Designer.cs @@ -0,0 +1,1485 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PortBlog.API.DbContexts; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + [DbContext(typeof(CvBlogContext))] + [Migration("20251028062356_User_RefreshTokens_Rerun")] + partial class User_RefreshTokens_Rerun + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.Property("AcademicId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("AcademicId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Degree") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("DegreeSpecialization") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("EndYear") + .HasColumnType("int"); + + b.Property("Institution") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartYear") + .HasColumnType("int"); + + b.HasKey("AcademicId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Academics"); + + b.HasData( + new + { + AcademicId = 1, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8319), + Degree = "High School", + EndYear = 2007, + Institution = "Pragati Little Public School", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8321), + ResumeId = 1, + StartYear = 2006 + }, + new + { + AcademicId = 2, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8990), + Degree = "Intermediate", + DegreeSpecialization = "MPC", + EndYear = 2009, + Institution = "Sri Chaitanya Junior College", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8991), + ResumeId = 1, + StartYear = 2007 + }, + new + { + AcademicId = 3, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(9095), + Degree = "BTech", + DegreeSpecialization = "ECE", + EndYear = 2013, + Institution = "Kakinada Institute of Technology & Science", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(9096), + ResumeId = 1, + StartYear = 2009 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.HasKey("BlogUrl"); + + b.ToTable("Blogs"); + + b.HasData( + new + { + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(6331), + Description = "Your Hub for Tech, DIY, and Innovation", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(6332), + Name = "Engineer's Odyssey" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Cache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(449) + .HasColumnType("varchar(449)"); + + b.Property("AbsoluteExpiration") + .HasColumnType("datetime(6)"); + + b.Property("ExpiresAtTime") + .HasColumnType("datetime(6)"); + + b.Property("SlidingExpirationInSeconds") + .HasColumnType("bigint"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longblob"); + + b.HasKey("Id"); + + b.ToTable("Cache"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Property("CandidateId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CandidateId")); + + b.Property("Address") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Avatar") + .HasColumnType("longtext"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Dob") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.HasKey("CandidateId"); + + b.ToTable("Candidates"); + + b.HasData( + new + { + CandidateId = 1, + Address = "Samalkot, Andhra Pradesh, India", + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 597, DateTimeKind.Local).AddTicks(6457), + Dob = new DateTime(1992, 5, 6, 0, 0, 0, 0, DateTimeKind.Unspecified), + Email = "bangararaju.kottedi@gmail.com", + FirstName = "Bangara Raju", + Gender = "Male", + LastName = "Kottedi", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 597, DateTimeKind.Local).AddTicks(6491), + Phone = "+91 9441212187" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.Property("CertificationId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CertificationId")); + + b.Property("CertificationLink") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CertificationName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("IssueDate") + .HasColumnType("datetime(6)"); + + b.Property("IssuingOrganization") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("CertificationId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Certifications"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ClientLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClientIp") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ClientLocation") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("SiteName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SiteUrl") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.ToTable("ClientLogs"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Property("ExperienceId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ExperienceId")); + + b.Property("Company") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ExperienceId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Experiences"); + + b.HasData( + new + { + ExperienceId = 1, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(3165), + Description = "", + EndDate = new DateTime(2016, 4, 25, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(3167), + ResumeId = 1, + StartDate = new DateTime(2015, 9, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Jr. Software Engineer" + }, + new + { + ExperienceId = 2, + Company = "Agility", + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4192), + Description = "", + EndDate = new DateTime(2022, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4193), + ResumeId = 1, + StartDate = new DateTime(2016, 5, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Web Developer" + }, + new + { + ExperienceId = 3, + Company = "Agility", + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4197), + Description = "", + EndDate = new DateTime(2022, 10, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4197), + ResumeId = 1, + StartDate = new DateTime(2022, 2, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Senior Web Developer" + }, + new + { + ExperienceId = 4, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4201), + Description = "", + EndDate = new DateTime(2024, 4, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4201), + ResumeId = 1, + StartDate = new DateTime(2022, 11, 4, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Technology Specialist" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("ExperienceId") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ExperienceId"); + + b.ToTable("ExperienceDetails"); + + b.HasData( + new + { + Id = 1, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6348), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6349), + Order = 1 + }, + new + { + Id = 2, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6828), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6829), + Order = 2 + }, + new + { + Id = 3, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6831), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6832), + Order = 1 + }, + new + { + Id = 4, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6834), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6834), + Order = 2 + }, + new + { + Id = 5, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6836), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6836), + Order = 1 + }, + new + { + Id = 6, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6842), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6842), + Order = 2 + }, + new + { + Id = 7, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6844), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6844), + Order = 1 + }, + new + { + Id = 8, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6846), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6846), + Order = 2 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.Property("HobbyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("HobbyId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("HobbyId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Hobbies"); + + b.HasData( + new + { + HobbyId = 1, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(5682), + Description = "Crafting Professional-Quality Websites with Precision.", + Icon = "fa-square-terminal", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(5683), + Name = "Web Development", + Order = 1, + ResumeId = 1 + }, + new + { + HobbyId = 2, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6359), + Description = "Streamlining and Simplifying Complex Tasks through Automation.", + Icon = "fa-robot", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6360), + Name = "Automation", + Order = 2, + ResumeId = 1 + }, + new + { + HobbyId = 3, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6363), + Description = "Sharing the knowledge and insights I’ve gathered along my journey.", + Icon = "fa-typewriter", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6363), + Name = "Blogging", + Order = 3, + ResumeId = 1 + }, + new + { + HobbyId = 4, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6365), + Description = "Exploring, embracing, and leveraging the latest advancements.", + Icon = "fa-lightbulb-gear", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6366), + Name = "Technology", + Order = 4, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FromEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SentStatus") + .HasColumnType("int"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ToEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("CandidateId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.Property("PostId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("PostId")); + + b.Property("Author") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("BlogUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.PrimitiveCollection("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Comments") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Image") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Likes") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PostUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("PostId"); + + b.HasIndex("BlogUrl"); + + b.ToTable("Posts"); + + b.HasData( + new + { + PostId = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(87), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(9329), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 2, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(390), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(387), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 3, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(394), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(392), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.Property("ProjectId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ProjectId")); + + b.PrimitiveCollection("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Challenges") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("ImagePath") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Impact") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("LessonsLearned") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Responsibilities") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Roles") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("TechnologiesUsed") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("ProjectId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Projects"); + + b.HasData( + new + { + ProjectId = 1, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(4003), + Description = "Business Process Management", + ImagePath = "bpm.jpg", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(4005), + Name = "Transfora (Business Process Management)", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 2, + Categories = "[\"Web Design\"]", + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5048), + Description = "Business Process Management", + ImagePath = "hcm.jpg", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5049), + Name = "Human Captial Management", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 3, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5120), + Description = "Business Process Management", + ImagePath = "hms.png", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5120), + Name = "Transfora (Business Process Management)", + Responsibilities = "Hosting, Integrating, Monitoring", + ResumeId = 1, + Roles = "Integration, Monitor", + TechnologiesUsed = ".NET, Angular" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.RefreshToken", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("TokenId")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DeviceInfo") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("JwtId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReplacedByToken") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Revoked") + .HasColumnType("tinyint(1)"); + + b.Property("Token") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("TokenId"); + + b.HasIndex("UserId"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Property("ResumeId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ResumeId")); + + b.Property("About") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("varchar(1000)"); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ResumeId"); + + b.HasIndex("CandidateId"); + + b.ToTable("Resumes"); + + b.HasData( + new + { + ResumeId = 1, + About = "I'm Full Stack Developer with 8+ years of hands-on experience in .NET development. Passionate and driven professional with expertise in .NET WebAPI, Angular, CI/CD, and a growing proficiency in Azure. I've successfully delivered robust applications, prioritizing efficiency and user experience. While I'm currently in the early stages of exploring Azure, I'm eager to expand my skill set and leverage cloud technologies to enhance scalability and performance. Known for my proactive approach and dedication to continuous learning, I'm committed to staying abreast of the latest technologies and methodologies to drive innovation and deliver exceptional results.", + CandidateId = 1, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(1505), + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(1512), + Order = 1, + Title = "Full Stack Developer" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.Property("FileId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("FileId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FileFormat") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Version") + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.HasKey("FileId"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.Property("SkillId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("SkillId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ProficiencyLevel") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("SkillId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Skills"); + + b.HasData( + new + { + SkillId = 1, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(784), + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(787), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 2, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1478), + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1481), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 3, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1484), + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1484), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 4, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1486), + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1486), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 5, + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1488), + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1488), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Facebook") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("GitHub") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Instagram") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Linkedin") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PersonalWebsite") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Twitter") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("BlogUrl"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("SocialLinks"); + + b.HasData( + new + { + Id = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(3502), + GitHub = "https://github.com/rajukottedi", + Linkedin = "https://in.linkedin.com/in/bangara-raju-kottedi-299072109", + ModifiedDate = new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(3506), + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("UserId")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("UserId"); + + b.ToTable("Users"); + + b.HasData( + new + { + UserId = 1, + CreatedAt = new DateTime(2025, 10, 28, 6, 23, 55, 601, DateTimeKind.Utc).AddTicks(8545), + Email = "bangararaju.kottedi@gmail.com", + Username = "rajukottedi" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Academics") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Certifications") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Experiences") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.HasOne("PortBlog.API.Entities.Experience", "Experience") + .WithMany("Details") + .HasForeignKey("ExperienceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Experience"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Hobbies") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany() + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany("Posts") + .HasForeignKey("BlogUrl") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Projects") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.RefreshToken", b => + { + b.HasOne("PortBlog.API.Entities.User", "User") + .WithMany("RefreshTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany("Resumes") + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("ResumeFile") + .HasForeignKey("PortBlog.API.Entities.ResumeFile", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Skills") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany() + .HasForeignKey("BlogUrl"); + + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("SocialLinks") + .HasForeignKey("PortBlog.API.Entities.SocialLinks", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Navigation("Posts"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Navigation("Resumes"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Navigation("Details"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Navigation("Academics"); + + b.Navigation("Certifications"); + + b.Navigation("Experiences"); + + b.Navigation("Hobbies"); + + b.Navigation("Projects"); + + b.Navigation("ResumeFile"); + + b.Navigation("Skills"); + + b.Navigation("SocialLinks"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.User", b => + { + b.Navigation("RefreshTokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PortBlog.API/Migrations/20251028062356_User_RefreshTokens_Rerun.cs b/PortBlog.API/Migrations/20251028062356_User_RefreshTokens_Rerun.cs new file mode 100644 index 0000000..204fc87 --- /dev/null +++ b/PortBlog.API/Migrations/20251028062356_User_RefreshTokens_Rerun.cs @@ -0,0 +1,561 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + /// + public partial class User_RefreshTokens_Rerun : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + UserId = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Username = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Email = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.UserId); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "RefreshTokens", + columns: table => new + { + TokenId = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(type: "int", nullable: false), + Token = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + JwtId = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ExpiryDate = table.Column(type: "datetime(6)", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + Revoked = table.Column(type: "tinyint(1)", nullable: false), + ReplacedByToken = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + DeviceInfo = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_RefreshTokens", x => x.TokenId); + table.ForeignKey( + name: "FK_RefreshTokens_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "UserId", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8319), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8321) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8990), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8991) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(9095), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(9096) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(6331), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(6332) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 597, DateTimeKind.Local).AddTicks(6457), new DateTime(2025, 10, 28, 11, 53, 55, 597, DateTimeKind.Local).AddTicks(6491) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6348), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6349) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6828), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6829) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6831), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6832) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6834), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6834) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6836), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6836) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6842), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6842) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6844), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6844) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6846), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6846) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(3165), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(3167) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4192), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4193) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4197), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4197) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4201), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4201) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(5682), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(5683) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6359), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6360) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6363), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6363) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6365), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6366) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(87), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(9329) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(390), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(387) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(394), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(392) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(4003), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(4005) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5048), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5049) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5120), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5120) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(1505), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(1512) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(784), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(787) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1478), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1481) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1484), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1484) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1486), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1486) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1488), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1488) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(3502), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(3506) }); + + migrationBuilder.InsertData( + table: "Users", + columns: new[] { "UserId", "CreatedAt", "Email", "Username" }, + values: new object[] { 1, new DateTime(2025, 10, 28, 6, 23, 55, 601, DateTimeKind.Utc).AddTicks(8545), "bangararaju.kottedi@gmail.com", "rajukottedi" }); + + migrationBuilder.CreateIndex( + name: "IX_RefreshTokens_UserId", + table: "RefreshTokens", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "RefreshTokens"); + + migrationBuilder.DropTable( + name: "Users"); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(4652), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(4653) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5447), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5448) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5558), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(5559) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(3195), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(3196) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 690, DateTimeKind.Local).AddTicks(9239), new DateTime(2025, 10, 28, 11, 34, 41, 690, DateTimeKind.Local).AddTicks(9275) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(3656), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(3657) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4150), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4150) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4152), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4153) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4154), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4155) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4156), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4156) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4161), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4161) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4163), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4163) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4164), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(4165) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(375), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(377) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1466), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1467) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1471), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1472) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1475), new DateTime(2025, 10, 28, 11, 34, 41, 694, DateTimeKind.Local).AddTicks(1475) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2045), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2046) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2725), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2725) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2728), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2729) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2730), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(2731) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7094), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(6266) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7426), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7423) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7429), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(7428) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(911), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(912) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2038), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2039) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2042), new DateTime(2025, 10, 28, 11, 34, 41, 693, DateTimeKind.Local).AddTicks(2043) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(7935), new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(7944) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(7751), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(7757) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8313), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8314) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8316), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8317) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8318), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8318) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8320), new DateTime(2025, 10, 28, 11, 34, 41, 692, DateTimeKind.Local).AddTicks(8320) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(9726), new DateTime(2025, 10, 28, 11, 34, 41, 691, DateTimeKind.Local).AddTicks(9728) }); + } + } +} diff --git a/PortBlog.API/Migrations/20251029015746_User_RefreshTokens_Update.Designer.cs b/PortBlog.API/Migrations/20251029015746_User_RefreshTokens_Update.Designer.cs new file mode 100644 index 0000000..d850422 --- /dev/null +++ b/PortBlog.API/Migrations/20251029015746_User_RefreshTokens_Update.Designer.cs @@ -0,0 +1,1485 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PortBlog.API.DbContexts; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + [DbContext(typeof(CvBlogContext))] + [Migration("20251029015746_User_RefreshTokens_Update")] + partial class User_RefreshTokens_Update + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.Property("AcademicId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("AcademicId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Degree") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("DegreeSpecialization") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("EndYear") + .HasColumnType("int"); + + b.Property("Institution") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartYear") + .HasColumnType("int"); + + b.HasKey("AcademicId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Academics"); + + b.HasData( + new + { + AcademicId = 1, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5159), + Degree = "High School", + EndYear = 2007, + Institution = "Pragati Little Public School", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5160), + ResumeId = 1, + StartYear = 2006 + }, + new + { + AcademicId = 2, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5783), + Degree = "Intermediate", + DegreeSpecialization = "MPC", + EndYear = 2009, + Institution = "Sri Chaitanya Junior College", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5784), + ResumeId = 1, + StartYear = 2007 + }, + new + { + AcademicId = 3, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5866), + Degree = "BTech", + DegreeSpecialization = "ECE", + EndYear = 2013, + Institution = "Kakinada Institute of Technology & Science", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5866), + ResumeId = 1, + StartYear = 2009 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.HasKey("BlogUrl"); + + b.ToTable("Blogs"); + + b.HasData( + new + { + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(1546), + Description = "Your Hub for Tech, DIY, and Innovation", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(1547), + Name = "Engineer's Odyssey" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Cache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(449) + .HasColumnType("varchar(449)"); + + b.Property("AbsoluteExpiration") + .HasColumnType("datetime(6)"); + + b.Property("ExpiresAtTime") + .HasColumnType("datetime(6)"); + + b.Property("SlidingExpirationInSeconds") + .HasColumnType("bigint"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longblob"); + + b.HasKey("Id"); + + b.ToTable("Cache"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Property("CandidateId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CandidateId")); + + b.Property("Address") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Avatar") + .HasColumnType("longtext"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Dob") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.HasKey("CandidateId"); + + b.ToTable("Candidates"); + + b.HasData( + new + { + CandidateId = 1, + Address = "Samalkot, Andhra Pradesh, India", + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(2626), + Dob = new DateTime(1992, 5, 6, 0, 0, 0, 0, DateTimeKind.Unspecified), + Email = "bangararaju.kottedi@gmail.com", + FirstName = "Bangara Raju", + Gender = "Male", + LastName = "Kottedi", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(2659), + Phone = "+91 9441212187" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.Property("CertificationId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CertificationId")); + + b.Property("CertificationLink") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CertificationName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("IssueDate") + .HasColumnType("datetime(6)"); + + b.Property("IssuingOrganization") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("CertificationId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Certifications"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ClientLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClientIp") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ClientLocation") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("SiteName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SiteUrl") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.ToTable("ClientLogs"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Property("ExperienceId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ExperienceId")); + + b.Property("Company") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ExperienceId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Experiences"); + + b.HasData( + new + { + ExperienceId = 1, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(7573), + Description = "", + EndDate = new DateTime(2016, 4, 25, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(7579), + ResumeId = 1, + StartDate = new DateTime(2015, 9, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Jr. Software Engineer" + }, + new + { + ExperienceId = 2, + Company = "Agility", + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8490), + Description = "", + EndDate = new DateTime(2022, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8490), + ResumeId = 1, + StartDate = new DateTime(2016, 5, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Web Developer" + }, + new + { + ExperienceId = 3, + Company = "Agility", + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8494), + Description = "", + EndDate = new DateTime(2022, 10, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8494), + ResumeId = 1, + StartDate = new DateTime(2022, 2, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Senior Web Developer" + }, + new + { + ExperienceId = 4, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8497), + Description = "", + EndDate = new DateTime(2024, 4, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8497), + ResumeId = 1, + StartDate = new DateTime(2022, 11, 4, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Technology Specialist" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("ExperienceId") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ExperienceId"); + + b.ToTable("ExperienceDetails"); + + b.HasData( + new + { + Id = 1, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(394), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(395), + Order = 1 + }, + new + { + Id = 2, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(804), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(805), + Order = 2 + }, + new + { + Id = 3, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(807), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(807), + Order = 1 + }, + new + { + Id = 4, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(808), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(808), + Order = 2 + }, + new + { + Id = 5, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(810), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(810), + Order = 1 + }, + new + { + Id = 6, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(815), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(815), + Order = 2 + }, + new + { + Id = 7, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(816), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(817), + Order = 1 + }, + new + { + Id = 8, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(818), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(818), + Order = 2 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.Property("HobbyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("HobbyId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("HobbyId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Hobbies"); + + b.HasData( + new + { + HobbyId = 1, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(2948), + Description = "Crafting Professional-Quality Websites with Precision.", + Icon = "fa-square-terminal", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(2949), + Name = "Web Development", + Order = 1, + ResumeId = 1 + }, + new + { + HobbyId = 2, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3600), + Description = "Streamlining and Simplifying Complex Tasks through Automation.", + Icon = "fa-robot", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3601), + Name = "Automation", + Order = 2, + ResumeId = 1 + }, + new + { + HobbyId = 3, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3603), + Description = "Sharing the knowledge and insights I’ve gathered along my journey.", + Icon = "fa-typewriter", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3604), + Name = "Blogging", + Order = 3, + ResumeId = 1 + }, + new + { + HobbyId = 4, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3605), + Description = "Exploring, embracing, and leveraging the latest advancements.", + Icon = "fa-lightbulb-gear", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3606), + Name = "Technology", + Order = 4, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FromEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SentStatus") + .HasColumnType("int"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ToEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("CandidateId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.Property("PostId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("PostId")); + + b.Property("Author") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("BlogUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.PrimitiveCollection("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Comments") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Image") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Likes") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PostUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("PostId"); + + b.HasIndex("BlogUrl"); + + b.ToTable("Posts"); + + b.HasData( + new + { + PostId = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4486), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(3878), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 2, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4730), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4727), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 3, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4733), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4731), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.Property("ProjectId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ProjectId")); + + b.PrimitiveCollection("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Challenges") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("ImagePath") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Impact") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("LessonsLearned") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Responsibilities") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Roles") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("TechnologiesUsed") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("ProjectId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Projects"); + + b.HasData( + new + { + ProjectId = 1, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(9719), + Description = "Business Process Management", + ImagePath = "bpm.jpg", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(9721), + Name = "Transfora (Business Process Management)", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 2, + Categories = "[\"Web Design\"]", + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(628), + Description = "Business Process Management", + ImagePath = "hcm.jpg", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(629), + Name = "Human Captial Management", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 3, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(632), + Description = "Business Process Management", + ImagePath = "hms.png", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(633), + Name = "Transfora (Business Process Management)", + Responsibilities = "Hosting, Integrating, Monitoring", + ResumeId = 1, + Roles = "Integration, Monitor", + TechnologiesUsed = ".NET, Angular" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.RefreshToken", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("TokenId")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DeviceInfo") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("JwtId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReplacedByToken") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Revoked") + .HasColumnType("tinyint(1)"); + + b.Property("Token") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("TokenId"); + + b.HasIndex("UserId"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Property("ResumeId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ResumeId")); + + b.Property("About") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("varchar(1000)"); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ResumeId"); + + b.HasIndex("CandidateId"); + + b.ToTable("Resumes"); + + b.HasData( + new + { + ResumeId = 1, + About = "I'm Full Stack Developer with 8+ years of hands-on experience in .NET development. Passionate and driven professional with expertise in .NET WebAPI, Angular, CI/CD, and a growing proficiency in Azure. I've successfully delivered robust applications, prioritizing efficiency and user experience. While I'm currently in the early stages of exploring Azure, I'm eager to expand my skill set and leverage cloud technologies to enhance scalability and performance. Known for my proactive approach and dedication to continuous learning, I'm committed to staying abreast of the latest technologies and methodologies to drive innovation and deliver exceptional results.", + CandidateId = 1, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(9805), + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(9812), + Order = 1, + Title = "Full Stack Developer" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.Property("FileId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("FileId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FileFormat") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Version") + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.HasKey("FileId"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.Property("SkillId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("SkillId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ProficiencyLevel") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("SkillId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Skills"); + + b.HasData( + new + { + SkillId = 1, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7273), + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7274), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 2, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7731), + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7731), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 3, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7733), + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7733), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 4, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7735), + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7735), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 5, + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7736), + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7737), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Facebook") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("GitHub") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Instagram") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Linkedin") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PersonalWebsite") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Twitter") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("BlogUrl"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("SocialLinks"); + + b.HasData( + new + { + Id = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(1156), + GitHub = "https://github.com/rajukottedi", + Linkedin = "https://in.linkedin.com/in/bangara-raju-kottedi-299072109", + ModifiedDate = new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(1157), + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("UserId")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("UserId"); + + b.ToTable("Users"); + + b.HasData( + new + { + UserId = 1, + CreatedAt = new DateTime(2025, 10, 29, 1, 57, 45, 782, DateTimeKind.Utc).AddTicks(1816), + Email = "bangararaju.kottedi@gmail.com", + Username = "rajukottedi" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Academics") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Certifications") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Experiences") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.HasOne("PortBlog.API.Entities.Experience", "Experience") + .WithMany("Details") + .HasForeignKey("ExperienceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Experience"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Hobbies") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany() + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany("Posts") + .HasForeignKey("BlogUrl") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Projects") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.RefreshToken", b => + { + b.HasOne("PortBlog.API.Entities.User", "User") + .WithMany("RefreshTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany("Resumes") + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("ResumeFile") + .HasForeignKey("PortBlog.API.Entities.ResumeFile", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Skills") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany() + .HasForeignKey("BlogUrl"); + + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("SocialLinks") + .HasForeignKey("PortBlog.API.Entities.SocialLinks", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Navigation("Posts"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Navigation("Resumes"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Navigation("Details"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Navigation("Academics"); + + b.Navigation("Certifications"); + + b.Navigation("Experiences"); + + b.Navigation("Hobbies"); + + b.Navigation("Projects"); + + b.Navigation("ResumeFile"); + + b.Navigation("Skills"); + + b.Navigation("SocialLinks"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.User", b => + { + b.Navigation("RefreshTokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PortBlog.API/Migrations/20251029015746_User_RefreshTokens_Update.cs b/PortBlog.API/Migrations/20251029015746_User_RefreshTokens_Update.cs new file mode 100644 index 0000000..da3e719 --- /dev/null +++ b/PortBlog.API/Migrations/20251029015746_User_RefreshTokens_Update.cs @@ -0,0 +1,509 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + /// + public partial class User_RefreshTokens_Update : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5159), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5160) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5783), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5784) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5866), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5866) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(1546), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(1547) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(2626), new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(2659) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(394), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(395) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(804), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(805) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(807), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(807) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(808), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(808) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(810), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(810) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(815), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(815) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(816), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(817) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(818), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(818) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(7573), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(7579) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8490), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8490) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8494), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8494) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8497), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8497) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(2948), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(2949) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3600), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3601) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3603), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3604) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3605), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3606) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4486), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(3878) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4730), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4727) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4733), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4731) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(9719), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(9721) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(628), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(629) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(632), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(633) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(9805), new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(9812) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7273), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7274) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7731), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7731) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7733), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7733) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7735), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7735) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7736), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7737) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(1156), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(1157) }); + + migrationBuilder.UpdateData( + table: "Users", + keyColumn: "UserId", + keyValue: 1, + column: "CreatedAt", + value: new DateTime(2025, 10, 29, 1, 57, 45, 782, DateTimeKind.Utc).AddTicks(1816)); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8319), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8321) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8990), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(8991) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(9095), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(9096) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(6331), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(6332) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 597, DateTimeKind.Local).AddTicks(6457), new DateTime(2025, 10, 28, 11, 53, 55, 597, DateTimeKind.Local).AddTicks(6491) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6348), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6349) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6828), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6829) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6831), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6832) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6834), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6834) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6836), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6836) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6842), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6842) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6844), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6844) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6846), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(6846) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(3165), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(3167) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4192), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4193) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4197), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4197) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4201), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(4201) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(5682), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(5683) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6359), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6360) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6363), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6363) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6365), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(6366) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(87), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(9329) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(390), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(387) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(394), new DateTime(2025, 10, 28, 11, 53, 55, 601, DateTimeKind.Local).AddTicks(392) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(4003), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(4005) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5048), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5049) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5120), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(5120) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(1505), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(1512) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(784), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(787) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1478), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1481) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1484), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1484) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1486), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1486) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1488), new DateTime(2025, 10, 28, 11, 53, 55, 600, DateTimeKind.Local).AddTicks(1488) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(3502), new DateTime(2025, 10, 28, 11, 53, 55, 599, DateTimeKind.Local).AddTicks(3506) }); + + migrationBuilder.UpdateData( + table: "Users", + keyColumn: "UserId", + keyValue: 1, + column: "CreatedAt", + value: new DateTime(2025, 10, 28, 6, 23, 55, 601, DateTimeKind.Utc).AddTicks(8545)); + } + } +} diff --git a/PortBlog.API/Migrations/20251113135040_update-refreshtoken.Designer.cs b/PortBlog.API/Migrations/20251113135040_update-refreshtoken.Designer.cs new file mode 100644 index 0000000..b19d9cb --- /dev/null +++ b/PortBlog.API/Migrations/20251113135040_update-refreshtoken.Designer.cs @@ -0,0 +1,1484 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PortBlog.API.DbContexts; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + [DbContext(typeof(CvBlogContext))] + [Migration("20251113135040_update-refreshtoken")] + partial class updaterefreshtoken + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.Property("AcademicId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("AcademicId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Degree") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("DegreeSpecialization") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("EndYear") + .HasColumnType("int"); + + b.Property("Institution") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartYear") + .HasColumnType("int"); + + b.HasKey("AcademicId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Academics"); + + b.HasData( + new + { + AcademicId = 1, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(1251), + Degree = "High School", + EndYear = 2007, + Institution = "Pragati Little Public School", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(1252), + ResumeId = 1, + StartYear = 2006 + }, + new + { + AcademicId = 2, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2024), + Degree = "Intermediate", + DegreeSpecialization = "MPC", + EndYear = 2009, + Institution = "Sri Chaitanya Junior College", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2024), + ResumeId = 1, + StartYear = 2007 + }, + new + { + AcademicId = 3, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2184), + Degree = "BTech", + DegreeSpecialization = "ECE", + EndYear = 2013, + Institution = "Kakinada Institute of Technology & Science", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2184), + ResumeId = 1, + StartYear = 2009 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.HasKey("BlogUrl"); + + b.ToTable("Blogs"); + + b.HasData( + new + { + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(9145), + Description = "Your Hub for Tech, DIY, and Innovation", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(9146), + Name = "Engineer's Odyssey" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Cache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(449) + .HasColumnType("varchar(449)"); + + b.Property("AbsoluteExpiration") + .HasColumnType("datetime(6)"); + + b.Property("ExpiresAtTime") + .HasColumnType("datetime(6)"); + + b.Property("SlidingExpirationInSeconds") + .HasColumnType("bigint"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longblob"); + + b.HasKey("Id"); + + b.ToTable("Cache"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Property("CandidateId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CandidateId")); + + b.Property("Address") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Avatar") + .HasColumnType("longtext"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Dob") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Gender") + .HasColumnType("longtext"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.HasKey("CandidateId"); + + b.ToTable("Candidates"); + + b.HasData( + new + { + CandidateId = 1, + Address = "Samalkot, Andhra Pradesh, India", + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 299, DateTimeKind.Local).AddTicks(5480), + Dob = new DateTime(1992, 5, 6, 0, 0, 0, 0, DateTimeKind.Unspecified), + Email = "bangararaju.kottedi@gmail.com", + FirstName = "Bangara Raju", + Gender = "Male", + LastName = "Kottedi", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 299, DateTimeKind.Local).AddTicks(5515), + Phone = "+91 9441212187" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.Property("CertificationId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CertificationId")); + + b.Property("CertificationLink") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CertificationName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("IssueDate") + .HasColumnType("datetime(6)"); + + b.Property("IssuingOrganization") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("CertificationId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Certifications"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ClientLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClientIp") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ClientLocation") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("SiteName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SiteUrl") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.ToTable("ClientLogs"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Property("ExperienceId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ExperienceId")); + + b.Property("Company") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("Location") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ExperienceId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Experiences"); + + b.HasData( + new + { + ExperienceId = 1, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(6786), + Description = "", + EndDate = new DateTime(2016, 4, 25, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(6793), + ResumeId = 1, + StartDate = new DateTime(2015, 9, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Jr. Software Engineer" + }, + new + { + ExperienceId = 2, + Company = "Agility", + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7965), + Description = "", + EndDate = new DateTime(2022, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7966), + ResumeId = 1, + StartDate = new DateTime(2016, 5, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Web Developer" + }, + new + { + ExperienceId = 3, + Company = "Agility", + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7970), + Description = "", + EndDate = new DateTime(2022, 10, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Kuwait", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7971), + ResumeId = 1, + StartDate = new DateTime(2022, 2, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Senior Web Developer" + }, + new + { + ExperienceId = 4, + Company = "Agility E Services", + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(8081), + Description = "", + EndDate = new DateTime(2024, 4, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + Location = "Hyderabad", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(8081), + ResumeId = 1, + StartDate = new DateTime(2022, 11, 4, 0, 0, 0, 0, DateTimeKind.Unspecified), + Title = "Technology Specialist" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("ExperienceId") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ExperienceId"); + + b.ToTable("ExperienceDetails"); + + b.HasData( + new + { + Id = 1, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(462), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(464), + Order = 1 + }, + new + { + Id = 2, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(988), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 1, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(988), + Order = 2 + }, + new + { + Id = 3, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(991), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(991), + Order = 1 + }, + new + { + Id = 4, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(993), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 2, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(993), + Order = 2 + }, + new + { + Id = 5, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(994), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(995), + Order = 1 + }, + new + { + Id = 6, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1004), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 3, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1005), + Order = 2 + }, + new + { + Id = 7, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1006), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1007), + Order = 1 + }, + new + { + Id = 8, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1008), + Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", + ExperienceId = 4, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1009), + Order = 2 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.Property("HobbyId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("HobbyId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("HobbyId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Hobbies"); + + b.HasData( + new + { + HobbyId = 1, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(8352), + Description = "Crafting Professional-Quality Websites with Precision.", + Icon = "fa-square-terminal", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(8353), + Name = "Web Development", + Order = 1, + ResumeId = 1 + }, + new + { + HobbyId = 2, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9201), + Description = "Streamlining and Simplifying Complex Tasks through Automation.", + Icon = "fa-robot", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9201), + Name = "Automation", + Order = 2, + ResumeId = 1 + }, + new + { + HobbyId = 3, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9204), + Description = "Sharing the knowledge and insights I’ve gathered along my journey.", + Icon = "fa-typewriter", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9205), + Name = "Blogging", + Order = 3, + ResumeId = 1 + }, + new + { + HobbyId = 4, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9207), + Description = "Exploring, embracing, and leveraging the latest advancements.", + Icon = "fa-lightbulb-gear", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9208), + Name = "Technology", + Order = 4, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FromEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("SentStatus") + .HasColumnType("int"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ToEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("CandidateId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.Property("PostId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("PostId")); + + b.Property("Author") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("BlogUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.PrimitiveCollection("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Comments") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Image") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Likes") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PostUrl") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("PostId"); + + b.HasIndex("BlogUrl"); + + b.ToTable("Posts"); + + b.HasData( + new + { + PostId = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(2910), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(2155), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 2, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3231), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3229), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }, + new + { + PostId = 3, + BlogUrl = "https://bangararaju.kottedi.in/blog", + Categories = "[\"Welcome\"]", + Comments = 0, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3236), + Description = "Hello World", + Likes = 0, + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3233), + PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", + Slug = "hello-world", + Title = "Hello World", + Views = 0 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.Property("ProjectId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ProjectId")); + + b.PrimitiveCollection("Categories") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Challenges") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("EndDate") + .HasColumnType("datetime(6)"); + + b.Property("ImagePath") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Impact") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("LessonsLearned") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Responsibilities") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Roles") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("StartDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("TechnologiesUsed") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("ProjectId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Projects"); + + b.HasData( + new + { + ProjectId = 1, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(6787), + Description = "Business Process Management", + ImagePath = "bpm.jpg", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(6789), + Name = "Transfora (Business Process Management)", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 2, + Categories = "[\"Web Design\"]", + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7979), + Description = "Business Process Management", + ImagePath = "hcm.jpg", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7980), + Name = "Human Captial Management", + Responsibilities = "Developing, Testing, Support", + ResumeId = 1, + Roles = "Coding, Reviewing, Testing", + TechnologiesUsed = ".NET, Angular" + }, + new + { + ProjectId = 3, + Categories = "[\"Web Development\"]", + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7983), + Description = "Business Process Management", + ImagePath = "hms.png", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7984), + Name = "Transfora (Business Process Management)", + Responsibilities = "Hosting, Integrating, Monitoring", + ResumeId = 1, + Roles = "Integration, Monitor", + TechnologiesUsed = ".NET, Angular" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.RefreshToken", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("TokenId")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DeviceInfo") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("JwtId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReplacedByToken") + .HasColumnType("longtext"); + + b.Property("Revoked") + .HasColumnType("tinyint(1)"); + + b.Property("Token") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("TokenId"); + + b.HasIndex("UserId"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Property("ResumeId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ResumeId")); + + b.Property("About") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("varchar(1000)"); + + b.Property("CandidateId") + .HasColumnType("int"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("ResumeId"); + + b.HasIndex("CandidateId"); + + b.ToTable("Resumes"); + + b.HasData( + new + { + ResumeId = 1, + About = "I'm Full Stack Developer with 8+ years of hands-on experience in .NET development. Passionate and driven professional with expertise in .NET WebAPI, Angular, CI/CD, and a growing proficiency in Azure. I've successfully delivered robust applications, prioritizing efficiency and user experience. While I'm currently in the early stages of exploring Azure, I'm eager to expand my skill set and leverage cloud technologies to enhance scalability and performance. Known for my proactive approach and dedication to continuous learning, I'm committed to staying abreast of the latest technologies and methodologies to drive innovation and deliver exceptional results.", + CandidateId = 1, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(4308), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(4316), + Order = 1, + Title = "Full Stack Developer" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.Property("FileId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("FileId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("FileFormat") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Version") + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.HasKey("FileId"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.Property("SkillId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("SkillId")); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ProficiencyLevel") + .HasColumnType("int"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.HasKey("SkillId"); + + b.HasIndex("ResumeId"); + + b.ToTable("Skills"); + + b.HasData( + new + { + SkillId = 1, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(3819), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(3820), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 2, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4333), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4333), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 3, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4335), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4336), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 4, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4337), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4338), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }, + new + { + SkillId = 5, + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4339), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4340), + Name = "Web Development", + ProficiencyLevel = 80, + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("BlogUrl") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CreatedBy") + .HasColumnType("longtext"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Facebook") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("GitHub") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Instagram") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Linkedin") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ModifiedBy") + .HasColumnType("longtext"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("PersonalWebsite") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ResumeId") + .HasColumnType("int"); + + b.Property("Twitter") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("BlogUrl"); + + b.HasIndex("ResumeId") + .IsUnique(); + + b.ToTable("SocialLinks"); + + b.HasData( + new + { + Id = 1, + BlogUrl = "https://bangararaju.kottedi.in/blog", + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(6144), + GitHub = "https://github.com/rajukottedi", + Linkedin = "https://in.linkedin.com/in/bangara-raju-kottedi-299072109", + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(6145), + ResumeId = 1 + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("UserId")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("UserId"); + + b.ToTable("Users"); + + b.HasData( + new + { + UserId = 1, + CreatedAt = new DateTime(2025, 11, 13, 13, 50, 39, 303, DateTimeKind.Utc).AddTicks(2327), + Email = "bangararaju.kottedi@gmail.com", + Username = "rajukottedi" + }); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Academics") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Certification", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Certifications") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Experiences") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ExperienceDetails", b => + { + b.HasOne("PortBlog.API.Entities.Experience", "Experience") + .WithMany("Details") + .HasForeignKey("ExperienceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Experience"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Hobby", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Hobbies") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Message", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany() + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Post", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany("Posts") + .HasForeignKey("BlogUrl") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Project", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Projects") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.RefreshToken", b => + { + b.HasOne("PortBlog.API.Entities.User", "User") + .WithMany("RefreshTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") + .WithMany("Resumes") + .HasForeignKey("CandidateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Candidate"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.ResumeFile", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("ResumeFile") + .HasForeignKey("PortBlog.API.Entities.ResumeFile", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Skill", b => + { + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithMany("Skills") + .HasForeignKey("ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.SocialLinks", b => + { + b.HasOne("PortBlog.API.Entities.Blog", "Blog") + .WithMany() + .HasForeignKey("BlogUrl"); + + b.HasOne("PortBlog.API.Entities.Resume", "Resume") + .WithOne("SocialLinks") + .HasForeignKey("PortBlog.API.Entities.SocialLinks", "ResumeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + + b.Navigation("Resume"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Blog", b => + { + b.Navigation("Posts"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => + { + b.Navigation("Resumes"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Experience", b => + { + b.Navigation("Details"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => + { + b.Navigation("Academics"); + + b.Navigation("Certifications"); + + b.Navigation("Experiences"); + + b.Navigation("Hobbies"); + + b.Navigation("Projects"); + + b.Navigation("ResumeFile"); + + b.Navigation("Skills"); + + b.Navigation("SocialLinks"); + }); + + modelBuilder.Entity("PortBlog.API.Entities.User", b => + { + b.Navigation("RefreshTokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PortBlog.API/Migrations/20251113135040_update-refreshtoken.cs b/PortBlog.API/Migrations/20251113135040_update-refreshtoken.cs new file mode 100644 index 0000000..b97a24c --- /dev/null +++ b/PortBlog.API/Migrations/20251113135040_update-refreshtoken.cs @@ -0,0 +1,537 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PortBlog.API.Migrations +{ + /// + public partial class updaterefreshtoken : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "ReplacedByToken", + table: "RefreshTokens", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(1251), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(1252) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2024), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2024) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2184), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2184) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(9145), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(9146) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 299, DateTimeKind.Local).AddTicks(5480), new DateTime(2025, 11, 13, 19, 20, 39, 299, DateTimeKind.Local).AddTicks(5515) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(462), new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(464) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(988), new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(988) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(991), new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(991) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(993), new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(993) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(994), new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(995) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1004), new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1005) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1006), new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1007) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1008), new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1009) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(6786), new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(6793) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7965), new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7966) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7970), new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7971) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(8081), new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(8081) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(8352), new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(8353) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9201), new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9201) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9204), new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9205) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9207), new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9208) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(2910), new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(2155) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3231), new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3229) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3236), new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3233) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(6787), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(6789) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7979), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7980) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7983), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7984) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(4308), new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(4316) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(3819), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(3820) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4333), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4333) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4335), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4336) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4337), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4338) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4339), new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4340) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(6144), new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(6145) }); + + migrationBuilder.UpdateData( + table: "Users", + keyColumn: "UserId", + keyValue: 1, + column: "CreatedAt", + value: new DateTime(2025, 11, 13, 13, 50, 39, 303, DateTimeKind.Utc).AddTicks(2327)); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "RefreshTokens", + keyColumn: "ReplacedByToken", + keyValue: null, + column: "ReplacedByToken", + value: ""); + + migrationBuilder.AlterColumn( + name: "ReplacedByToken", + table: "RefreshTokens", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5159), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5160) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5783), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5784) }); + + migrationBuilder.UpdateData( + table: "Academics", + keyColumn: "AcademicId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5866), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(5866) }); + + migrationBuilder.UpdateData( + table: "Blogs", + keyColumn: "BlogUrl", + keyValue: "https://bangararaju.kottedi.in/blog", + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(1546), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(1547) }); + + migrationBuilder.UpdateData( + table: "Candidates", + keyColumn: "CandidateId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(2626), new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(2659) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(394), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(395) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(804), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(805) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(807), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(807) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(808), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(808) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(810), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(810) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 6, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(815), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(815) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 7, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(816), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(817) }); + + migrationBuilder.UpdateData( + table: "ExperienceDetails", + keyColumn: "Id", + keyValue: 8, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(818), new DateTime(2025, 10, 29, 7, 27, 45, 782, DateTimeKind.Local).AddTicks(818) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(7573), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(7579) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8490), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8490) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8494), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8494) }); + + migrationBuilder.UpdateData( + table: "Experiences", + keyColumn: "ExperienceId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8497), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(8497) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(2948), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(2949) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3600), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3601) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3603), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3604) }); + + migrationBuilder.UpdateData( + table: "Hobbies", + keyColumn: "HobbyId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3605), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(3606) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4486), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(3878) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4730), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4727) }); + + migrationBuilder.UpdateData( + table: "Posts", + keyColumn: "PostId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4733), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(4731) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(9719), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(9721) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(628), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(629) }); + + migrationBuilder.UpdateData( + table: "Projects", + keyColumn: "ProjectId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(632), new DateTime(2025, 10, 29, 7, 27, 45, 781, DateTimeKind.Local).AddTicks(633) }); + + migrationBuilder.UpdateData( + table: "Resumes", + keyColumn: "ResumeId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(9805), new DateTime(2025, 10, 29, 7, 27, 45, 779, DateTimeKind.Local).AddTicks(9812) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7273), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7274) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 2, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7731), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7731) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 3, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7733), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7733) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 4, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7735), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7735) }); + + migrationBuilder.UpdateData( + table: "Skills", + keyColumn: "SkillId", + keyValue: 5, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7736), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(7737) }); + + migrationBuilder.UpdateData( + table: "SocialLinks", + keyColumn: "Id", + keyValue: 1, + columns: new[] { "CreatedDate", "ModifiedDate" }, + values: new object[] { new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(1156), new DateTime(2025, 10, 29, 7, 27, 45, 780, DateTimeKind.Local).AddTicks(1157) }); + + migrationBuilder.UpdateData( + table: "Users", + keyColumn: "UserId", + keyValue: 1, + column: "CreatedAt", + value: new DateTime(2025, 10, 29, 1, 57, 45, 782, DateTimeKind.Utc).AddTicks(1816)); + } + } +} diff --git a/PortBlog.API/Migrations/CvBlogContextModelSnapshot.cs b/PortBlog.API/Migrations/CvBlogContextModelSnapshot.cs index a0d1f54..ad14152 100644 --- a/PortBlog.API/Migrations/CvBlogContextModelSnapshot.cs +++ b/PortBlog.API/Migrations/CvBlogContextModelSnapshot.cs @@ -17,7 +17,7 @@ namespace PortBlog.API.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("ProductVersion", "9.0.9") .HasAnnotation("Relational:MaxIdentifierLength", 64); MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); @@ -75,35 +75,35 @@ namespace PortBlog.API.Migrations new { AcademicId = 1, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8945), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(1251), Degree = "High School", EndYear = 2007, Institution = "Pragati Little Public School", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8945), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(1252), ResumeId = 1, StartYear = 2006 }, new { AcademicId = 2, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8948), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2024), Degree = "Intermediate", DegreeSpecialization = "MPC", EndYear = 2009, Institution = "Sri Chaitanya Junior College", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8949), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2024), ResumeId = 1, StartYear = 2007 }, new { AcademicId = 3, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8950), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2184), Degree = "BTech", DegreeSpecialization = "ECE", EndYear = 2013, Institution = "Kakinada Institute of Technology & Science", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8951), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(2184), ResumeId = 1, StartYear = 2009 }); @@ -144,13 +144,38 @@ namespace PortBlog.API.Migrations new { BlogUrl = "https://bangararaju.kottedi.in/blog", - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9023), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(9145), Description = "Your Hub for Tech, DIY, and Innovation", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9023), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(9146), Name = "Engineer's Odyssey" }); }); + modelBuilder.Entity("PortBlog.API.Entities.Cache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(449) + .HasColumnType("varchar(449)"); + + b.Property("AbsoluteExpiration") + .HasColumnType("datetime(6)"); + + b.Property("ExpiresAtTime") + .HasColumnType("datetime(6)"); + + b.Property("SlidingExpirationInSeconds") + .HasColumnType("bigint"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longblob"); + + b.HasKey("Id"); + + b.ToTable("Cache"); + }); + modelBuilder.Entity("PortBlog.API.Entities.Candidate", b => { b.Property("CandidateId") @@ -213,13 +238,13 @@ namespace PortBlog.API.Migrations { CandidateId = 1, Address = "Samalkot, Andhra Pradesh, India", - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8726), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 299, DateTimeKind.Local).AddTicks(5480), Dob = new DateTime(1992, 5, 6, 0, 0, 0, 0, DateTimeKind.Unspecified), Email = "bangararaju.kottedi@gmail.com", FirstName = "Bangara Raju", Gender = "Male", LastName = "Kottedi", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8742), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 299, DateTimeKind.Local).AddTicks(5515), Phone = "+91 9441212187" }); }); @@ -366,11 +391,11 @@ namespace PortBlog.API.Migrations { ExperienceId = 1, Company = "Agility E Services", - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9068), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(6786), Description = "", EndDate = new DateTime(2016, 4, 25, 0, 0, 0, 0, DateTimeKind.Unspecified), Location = "Hyderabad", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9068), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(6793), ResumeId = 1, StartDate = new DateTime(2015, 9, 2, 0, 0, 0, 0, DateTimeKind.Unspecified), Title = "Jr. Software Engineer" @@ -379,11 +404,11 @@ namespace PortBlog.API.Migrations { ExperienceId = 2, Company = "Agility", - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9072), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7965), Description = "", EndDate = new DateTime(2022, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), Location = "Kuwait", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9073), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7966), ResumeId = 1, StartDate = new DateTime(2016, 5, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), Title = "Web Developer" @@ -392,11 +417,11 @@ namespace PortBlog.API.Migrations { ExperienceId = 3, Company = "Agility", - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9075), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7970), Description = "", EndDate = new DateTime(2022, 10, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), Location = "Kuwait", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9075), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(7971), ResumeId = 1, StartDate = new DateTime(2022, 2, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), Title = "Senior Web Developer" @@ -405,11 +430,11 @@ namespace PortBlog.API.Migrations { ExperienceId = 4, Company = "Agility E Services", - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9077), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(8081), Description = "", EndDate = new DateTime(2024, 4, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), Location = "Hyderabad", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9077), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(8081), ResumeId = 1, StartDate = new DateTime(2022, 11, 4, 0, 0, 0, 0, DateTimeKind.Unspecified), Title = "Technology Specialist" @@ -457,73 +482,73 @@ namespace PortBlog.API.Migrations new { Id = 1, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9096), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(462), Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", ExperienceId = 1, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9096), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(464), Order = 1 }, new { Id = 2, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9099), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(988), Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", ExperienceId = 1, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9100), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(988), Order = 2 }, new { Id = 3, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9101), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(991), Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", ExperienceId = 2, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9101), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(991), Order = 1 }, new { Id = 4, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9102), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(993), Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", ExperienceId = 2, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9102), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(993), Order = 2 }, new { Id = 5, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9103), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(994), Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", ExperienceId = 3, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9103), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(995), Order = 1 }, new { Id = 6, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9105), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1004), Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", ExperienceId = 3, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9105), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1005), Order = 2 }, new { Id = 7, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9106), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1006), Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", ExperienceId = 4, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9106), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1007), Order = 1 }, new { Id = 8, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9107), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1008), Details = "Worked on the YouTube Captions team, in Javascript and Python to plan, to design and develop the full stack to add and edit Automatic Speech Recognition captions.", ExperienceId = 4, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9108), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 303, DateTimeKind.Local).AddTicks(1009), Order = 2 }); }); @@ -578,10 +603,10 @@ namespace PortBlog.API.Migrations new { HobbyId = 1, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8912), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(8352), Description = "Crafting Professional-Quality Websites with Precision.", Icon = "fa-square-terminal", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8913), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(8353), Name = "Web Development", Order = 1, ResumeId = 1 @@ -589,10 +614,10 @@ namespace PortBlog.API.Migrations new { HobbyId = 2, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8917), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9201), Description = "Streamlining and Simplifying Complex Tasks through Automation.", Icon = "fa-robot", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8918), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9201), Name = "Automation", Order = 2, ResumeId = 1 @@ -600,10 +625,10 @@ namespace PortBlog.API.Migrations new { HobbyId = 3, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8919), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9204), Description = "Sharing the knowledge and insights I’ve gathered along my journey.", Icon = "fa-typewriter", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8919), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9205), Name = "Blogging", Order = 3, ResumeId = 1 @@ -611,10 +636,10 @@ namespace PortBlog.API.Migrations new { HobbyId = 4, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8921), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9207), Description = "Exploring, embracing, and leveraging the latest advancements.", Icon = "fa-lightbulb-gear", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8921), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(9208), Name = "Technology", Order = 4, ResumeId = 1 @@ -634,8 +659,7 @@ namespace PortBlog.API.Migrations b.Property("Content") .IsRequired() - .HasMaxLength(500) - .HasColumnType("varchar(500)"); + .HasColumnType("longtext"); b.Property("CreatedDate") .HasColumnType("datetime(6)"); @@ -687,7 +711,7 @@ namespace PortBlog.API.Migrations .HasMaxLength(200) .HasColumnType("varchar(200)"); - b.Property("Categories") + b.PrimitiveCollection("Categories") .IsRequired() .HasMaxLength(200) .HasColumnType("varchar(200)"); @@ -750,10 +774,10 @@ namespace PortBlog.API.Migrations BlogUrl = "https://bangararaju.kottedi.in/blog", Categories = "[\"Welcome\"]", Comments = 0, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9042), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(2910), Description = "Hello World", Likes = 0, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9038), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(2155), PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", Slug = "hello-world", Title = "Hello World", @@ -765,10 +789,10 @@ namespace PortBlog.API.Migrations BlogUrl = "https://bangararaju.kottedi.in/blog", Categories = "[\"Welcome\"]", Comments = 0, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9047), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3231), Description = "Hello World", Likes = 0, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9045), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3229), PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", Slug = "hello-world", Title = "Hello World", @@ -780,10 +804,10 @@ namespace PortBlog.API.Migrations BlogUrl = "https://bangararaju.kottedi.in/blog", Categories = "[\"Welcome\"]", Comments = 0, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9049), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3236), Description = "Hello World", Likes = 0, - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9048), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 302, DateTimeKind.Local).AddTicks(3233), PostUrl = "https://bangararaju.kottedi.in/blog/hello-world", Slug = "hello-world", Title = "Hello World", @@ -799,7 +823,7 @@ namespace PortBlog.API.Migrations MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("ProjectId")); - b.Property("Categories") + b.PrimitiveCollection("Categories") .IsRequired() .HasMaxLength(200) .HasColumnType("varchar(200)"); @@ -881,10 +905,10 @@ namespace PortBlog.API.Migrations { ProjectId = 1, Categories = "[\"Web Development\"]", - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8997), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(6787), Description = "Business Process Management", ImagePath = "bpm.jpg", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8997), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(6789), Name = "Transfora (Business Process Management)", Responsibilities = "Developing, Testing, Support", ResumeId = 1, @@ -895,10 +919,10 @@ namespace PortBlog.API.Migrations { ProjectId = 2, Categories = "[\"Web Design\"]", - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9003), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7979), Description = "Business Process Management", ImagePath = "hcm.jpg", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9003), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7980), Name = "Human Captial Management", Responsibilities = "Developing, Testing, Support", ResumeId = 1, @@ -909,10 +933,10 @@ namespace PortBlog.API.Migrations { ProjectId = 3, Categories = "[\"Web Development\"]", - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9006), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7983), Description = "Business Process Management", ImagePath = "hms.png", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(9006), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(7984), Name = "Transfora (Business Process Management)", Responsibilities = "Hosting, Integrating, Monitoring", ResumeId = 1, @@ -921,6 +945,48 @@ namespace PortBlog.API.Migrations }); }); + modelBuilder.Entity("PortBlog.API.Entities.RefreshToken", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("TokenId")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DeviceInfo") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("JwtId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReplacedByToken") + .HasColumnType("longtext"); + + b.Property("Revoked") + .HasColumnType("tinyint(1)"); + + b.Property("Token") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("TokenId"); + + b.HasIndex("UserId"); + + b.ToTable("RefreshTokens"); + }); + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => { b.Property("ResumeId") @@ -969,8 +1035,8 @@ namespace PortBlog.API.Migrations ResumeId = 1, About = "I'm Full Stack Developer with 8+ years of hands-on experience in .NET development. Passionate and driven professional with expertise in .NET WebAPI, Angular, CI/CD, and a growing proficiency in Azure. I've successfully delivered robust applications, prioritizing efficiency and user experience. While I'm currently in the early stages of exploring Azure, I'm eager to expand my skill set and leverage cloud technologies to enhance scalability and performance. Known for my proactive approach and dedication to continuous learning, I'm committed to staying abreast of the latest technologies and methodologies to drive innovation and deliver exceptional results.", CandidateId = 1, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8874), - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8874), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(4308), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(4316), Order = 1, Title = "Full Stack Developer" }); @@ -1071,8 +1137,8 @@ namespace PortBlog.API.Migrations new { SkillId = 1, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8968), - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8968), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(3819), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(3820), Name = "Web Development", ProficiencyLevel = 80, ResumeId = 1 @@ -1080,8 +1146,8 @@ namespace PortBlog.API.Migrations new { SkillId = 2, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8971), - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8972), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4333), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4333), Name = "Web Development", ProficiencyLevel = 80, ResumeId = 1 @@ -1089,8 +1155,8 @@ namespace PortBlog.API.Migrations new { SkillId = 3, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8973), - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8973), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4335), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4336), Name = "Web Development", ProficiencyLevel = 80, ResumeId = 1 @@ -1098,8 +1164,8 @@ namespace PortBlog.API.Migrations new { SkillId = 4, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8974), - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8974), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4337), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4338), Name = "Web Development", ProficiencyLevel = 80, ResumeId = 1 @@ -1107,8 +1173,8 @@ namespace PortBlog.API.Migrations new { SkillId = 5, - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8975), - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8976), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4339), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 301, DateTimeKind.Local).AddTicks(4340), Name = "Web Development", ProficiencyLevel = 80, ResumeId = 1 @@ -1181,14 +1247,47 @@ namespace PortBlog.API.Migrations { Id = 1, BlogUrl = "https://bangararaju.kottedi.in/blog", - CreatedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8894), + CreatedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(6144), GitHub = "https://github.com/rajukottedi", Linkedin = "https://in.linkedin.com/in/bangara-raju-kottedi-299072109", - ModifiedDate = new DateTime(2024, 5, 7, 23, 8, 7, 980, DateTimeKind.Local).AddTicks(8895), + ModifiedDate = new DateTime(2025, 11, 13, 19, 20, 39, 300, DateTimeKind.Local).AddTicks(6145), ResumeId = 1 }); }); + modelBuilder.Entity("PortBlog.API.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("UserId")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("UserId"); + + b.ToTable("Users"); + + b.HasData( + new + { + UserId = 1, + CreatedAt = new DateTime(2025, 11, 13, 13, 50, 39, 303, DateTimeKind.Utc).AddTicks(2327), + Email = "bangararaju.kottedi@gmail.com", + Username = "rajukottedi" + }); + }); + modelBuilder.Entity("PortBlog.API.Entities.Academic", b => { b.HasOne("PortBlog.API.Entities.Resume", "Resume") @@ -1277,6 +1376,17 @@ namespace PortBlog.API.Migrations b.Navigation("Resume"); }); + modelBuilder.Entity("PortBlog.API.Entities.RefreshToken", b => + { + b.HasOne("PortBlog.API.Entities.User", "User") + .WithMany("RefreshTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + modelBuilder.Entity("PortBlog.API.Entities.Resume", b => { b.HasOne("PortBlog.API.Entities.Candidate", "Candidate") @@ -1360,6 +1470,11 @@ namespace PortBlog.API.Migrations b.Navigation("SocialLinks"); }); + + modelBuilder.Entity("PortBlog.API.Entities.User", b => + { + b.Navigation("RefreshTokens"); + }); #pragma warning restore 612, 618 } } diff --git a/PortBlog.API/Models/MailSettingsDto.cs b/PortBlog.API/Models/MailSettingsDto.cs index 570e4e0..503c7b2 100644 --- a/PortBlog.API/Models/MailSettingsDto.cs +++ b/PortBlog.API/Models/MailSettingsDto.cs @@ -11,5 +11,7 @@ public string Password { get; set; } = string.Empty; public bool Enable { get; set; } = false; + + public string Domain { get; set; } = string.Empty; } } diff --git a/PortBlog.API/Models/MessageSendDto.cs b/PortBlog.API/Models/MessageSendDto.cs index 803fcf2..e59fbb3 100644 --- a/PortBlog.API/Models/MessageSendDto.cs +++ b/PortBlog.API/Models/MessageSendDto.cs @@ -9,8 +9,6 @@ namespace PortBlog.API.Models public string FromEmail { get; set; } = string.Empty; - public string CandidateName { get; set; } = string.Empty; - public string ToEmail { get; set; } = string.Empty; public string Subject { get; set; } = string.Empty; diff --git a/PortBlog.API/Models/OtpMailModel.cs b/PortBlog.API/Models/OtpMailModel.cs new file mode 100644 index 0000000..cd22fd0 --- /dev/null +++ b/PortBlog.API/Models/OtpMailModel.cs @@ -0,0 +1,9 @@ +namespace PortBlog.API.Models +{ + public class OtpMailModel + { + public string Name { get; set; } = string.Empty; + public string OtpCode { get; set; } = string.Empty; + public int ExpiryMinutes { get; set; } = 3; + } +} diff --git a/PortBlog.API/Models/VerifyOtpRequest.cs b/PortBlog.API/Models/VerifyOtpRequest.cs new file mode 100644 index 0000000..86e5b3f --- /dev/null +++ b/PortBlog.API/Models/VerifyOtpRequest.cs @@ -0,0 +1,8 @@ +namespace PortBlog.API.Models +{ + public class VerifyOtpRequest + { + public string UserId { get; set; } = string.Empty; + public string OtpCode { get; set; } = string.Empty; + } +} diff --git a/PortBlog.API/Options/JwtAuthenticationOptions.cs b/PortBlog.API/Options/JwtAuthenticationOptions.cs new file mode 100644 index 0000000..447815f --- /dev/null +++ b/PortBlog.API/Options/JwtAuthenticationOptions.cs @@ -0,0 +1,11 @@ +namespace PortBlog.API.Options +{ + public class JwtAuthenticationOptions + { + required public string SecretKey { get; set; } + + required public int AccessTokenExpiryInMinutes { get; set; } + + required public int RefreshTokenExpiryInHours { get; set; } + } +} diff --git a/PortBlog.API/PortBlog.API.csproj b/PortBlog.API/PortBlog.API.csproj index fed1c6f..303fa5a 100644 --- a/PortBlog.API/PortBlog.API.csproj +++ b/PortBlog.API/PortBlog.API.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable True @@ -10,22 +10,30 @@ - - - - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - + + + + + + + + + + + diff --git a/PortBlog.API/PortBlog.API.xml b/PortBlog.API/PortBlog.API.xml index 8318188..0bd7480 100644 --- a/PortBlog.API/PortBlog.API.xml +++ b/PortBlog.API/PortBlog.API.xml @@ -4,6 +4,62 @@ PortBlog.API + + + Get hobbies of the candidate by candidateid + + The id of the candidate whose hobbies to get + Hobbies of the candidate + Returns the requested hobbies of the candidate + + + + Get Candidate details with social links by candidateid + + The id of the candidate whose detials to get with social links + Candidate details with sociallinks + Returns the requested candidate details with social links + + + + Get Candidate resume by candidateid + + The id of the candidate whose resume to get + Candidate resume + Returns the requested candidate resume + + + + Get Candidate projects by candidateid + + The id of the candidate whose projects to get + Candidate projects + Returns the requested candidate projects + + + + Controller for handling authentication-related operations. + + + + + Controller for handling authentication-related operations. + + + + + Generates a One-Time Password (OTP) for the specified candidate and sends it via email. + + The ID of the candidate for whom the OTP is generated. + An ActionResult indicating the result of the operation. + + + + Verifies the One-Time Password (OTP) for the specified user. + + The request containing the user ID and OTP code to verify. + An ActionResult indicating the result of the verification. + Get CV details of the candidate by candidateid. @@ -181,6 +237,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CV details of the candidate @@ -271,5 +399,13 @@ The work experiences of the candidate + + + Validates the provided OTP against the secret key. + + The Base32 encoded secret key. + The OTP to validate. + True if the OTP is valid; otherwise, false. + diff --git a/PortBlog.API/Program.cs b/PortBlog.API/Program.cs index a7dfb05..ac46b28 100644 --- a/PortBlog.API/Program.cs +++ b/PortBlog.API/Program.cs @@ -1,33 +1,37 @@ using Asp.Versioning; using Asp.Versioning.ApiExplorer; +using KBR.Cache.Extensions; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.FileProviders; +using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using PortBlog.API.DbContexts; using PortBlog.API.Extensions; using PortBlog.API.Middleware; using Serilog; using System.Reflection; +using System.Text; var builder = WebApplication.CreateBuilder(args); +var loggerConfiguration = new LoggerConfiguration(); + if (builder.Environment.IsDevelopment()) { - Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .WriteTo.Console() - .WriteTo.File("logs/portblog.txt", rollingInterval: RollingInterval.Day) - .CreateLogger(); + loggerConfiguration = loggerConfiguration.MinimumLevel.Debug() + .WriteTo.Console(); } else { - Log.Logger = new LoggerConfiguration() - .MinimumLevel.Information() + loggerConfiguration = loggerConfiguration.MinimumLevel.Information(); +} + +Log.Logger = loggerConfiguration .WriteTo.File("logs/portblog.txt", rollingInterval: RollingInterval.Day) .CreateLogger(); -} var urls = builder.Configuration.GetSection("Urls"); @@ -39,22 +43,25 @@ if (!string.IsNullOrEmpty(urls.Value)) } var allowedCorsOrigins = builder.Configuration.GetSection("AllowedCorsOrigins"); +string[] origins = Array.Empty(); if (!String.IsNullOrEmpty(allowedCorsOrigins.Value)) { - var origins = allowedCorsOrigins.Value.Split(","); - - builder.Services.AddCors(options => - { - options.AddDefaultPolicy( - policy => - { - policy.WithOrigins(origins); - policy.AllowAnyHeader(); - }); - }); + origins = allowedCorsOrigins.Value.Split(",", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); } +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy( + policy => + { + policy.WithOrigins(origins); + policy.AllowAnyHeader(); + policy.AllowAnyMethod(); + policy.AllowCredentials(); + }); +}); + builder.Host.UseSerilog(); // Add services to the container. @@ -88,7 +95,8 @@ builder.Services builder.Services.AddRepositories(); builder.Services.AddServices(); -builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); +builder.Services.AddAutoMapper(cfg => cfg.AddMaps(AppDomain.CurrentDomain.GetAssemblies())); +builder.Services.AddCache(builder.Configuration); // Registering API Versioning Specification services @@ -108,7 +116,7 @@ var apiVersionDescriptionProvider = builder.Services.BuildServiceProvider() builder.Services.AddSwaggerGen(c => { - foreach(var description in apiVersionDescriptionProvider.ApiVersionDescriptions) + foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions) { c.SwaggerDoc( $"{description.GroupName}", @@ -146,14 +154,56 @@ builder.Services.AddSwaggerGen(c => In = ParameterLocation.Header }; + // JWT Bearer Security Definition + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = "JWT Authorization header using the Bearer scheme.\nExample: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..'", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = "Bearer", + BearerFormat = "JWT" + }); + + var bearerScheme = new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }; + var requirement = new OpenApiSecurityRequirement() { - {key, new List {} } + {key, new List {} }, + {bearerScheme, new List{} } }; c.AddSecurityRequirement(requirement); }); +var key = Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]); + +builder.Services.AddAuthentication(options => +{ + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; +}) +.AddJwtBearer(options => +{ + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + ValidateIssuerSigningKey = true, + ValidIssuer = builder.Configuration["Jwt:Issuer"], + ValidAudience = builder.Configuration["Jwt:Audience"], + IssuerSigningKey = new SymmetricSecurityKey(key) + }; +}); + var app = builder.Build(); app.UseCors(); @@ -170,7 +220,7 @@ if (app.Environment.IsDevelopment()) app.UseSwaggerUI(setupAction => { var descriptions = app.DescribeApiVersions(); - foreach(var description in descriptions) + foreach (var description in descriptions) { setupAction.SwaggerEndpoint( $"/swagger/{description.GroupName}/swagger.json", @@ -185,9 +235,11 @@ app.UseHttpsRedirection(); app.UseStaticFiles(new StaticFileOptions() { FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), @"Images")), - RequestPath = new PathString("/images") + RequestPath = new PathString("/images") }); +app.UseAuthentication(); + app.UseAuthorization(); app.UseMiddleware(); diff --git a/PortBlog.API/Properties/launchSettings.json b/PortBlog.API/Properties/launchSettings.json index 229725e..f12ed9c 100644 --- a/PortBlog.API/Properties/launchSettings.json +++ b/PortBlog.API/Properties/launchSettings.json @@ -1,33 +1,23 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:37113", - "sslPort": 44357 - } - }, +{ "profiles": { "http": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "http://localhost:5039", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5039" }, "PortBlog.API": { "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "https://localhost:7013;http://localhost:5039", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7013;http://localhost:5039" }, "IIS Express": { "commandName": "IISExpress", @@ -37,5 +27,14 @@ "ASPNETCORE_ENVIRONMENT": "Development" } } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:37113", + "sslPort": 44357 + } } -} +} \ No newline at end of file diff --git a/PortBlog.API/Repositories/CandidateRepository.cs b/PortBlog.API/Repositories/CandidateRepository.cs index e070435..2852fee 100644 --- a/PortBlog.API/Repositories/CandidateRepository.cs +++ b/PortBlog.API/Repositories/CandidateRepository.cs @@ -23,5 +23,10 @@ namespace PortBlog.API.Repositories { return await _cvBlogContext.Candidates.FirstOrDefaultAsync(c => c.CandidateId == id); } + + public async Task GetCandidateAsync(string email) + { + return await _cvBlogContext.Candidates.FirstOrDefaultAsync(c => c.Email == email); + } } } diff --git a/PortBlog.API/Repositories/Contracts/ICandidateRepository.cs b/PortBlog.API/Repositories/Contracts/ICandidateRepository.cs index 6761126..a406fa9 100644 --- a/PortBlog.API/Repositories/Contracts/ICandidateRepository.cs +++ b/PortBlog.API/Repositories/Contracts/ICandidateRepository.cs @@ -6,6 +6,8 @@ namespace PortBlog.API.Repositories.Contracts { Task GetCandidateAsync(int id); + Task GetCandidateAsync(string email); + Task CandidateExistAsync(int candidateId); } } diff --git a/PortBlog.API/Services/AuthService.cs b/PortBlog.API/Services/AuthService.cs new file mode 100644 index 0000000..998c57d --- /dev/null +++ b/PortBlog.API/Services/AuthService.cs @@ -0,0 +1,153 @@ +using KBR.Cache; +using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using OtpNet; +using PortBlog.API.DbContexts; +using PortBlog.API.Entities; +using PortBlog.API.Services.Contracts; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Security.Cryptography; +using System.Text; + +namespace PortBlog.API.Services +{ + public class AuthService : IAuthService + { + private readonly IConfiguration configuration; + private readonly IAppDistributedCache cache; + private readonly CvBlogContext _context; + + public AuthService(IConfiguration configuration, IAppDistributedCache cache, CvBlogContext context) + { + this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); + this.cache = cache ?? throw new ArgumentNullException(nameof(cache)); + this._context = context ?? throw new ArgumentNullException(nameof(context)); + } + + public async Task GenerateOtp(string email, CancellationToken ct = default) + { + var secretKey = KeyGeneration.GenerateRandomKey(20); + var secretKeyBase32 = Base32Encoding.ToString(secretKey); + var otp = this.GenerateOtp(secretKeyBase32); + + await CacheHelpers.SetUserSecretsCacheAsync(cache, email, secretKeyBase32, ct); + + return otp; + } + + /// + /// Validates the provided OTP against the secret key. + /// + /// The Base32 encoded secret key. + /// The OTP to validate. + /// True if the OTP is valid; otherwise, false. + public bool ValidateOtp(string secretKey, string otp) + { + var key = Base32Encoding.ToBytes(secretKey); + var otpExpiryInMinutes = configuration.GetValue("OtpExpiryInMinutes", 3); + var totp = new Totp(key, step: otpExpiryInMinutes * 60); + + return totp.VerifyTotp(DateTime.UtcNow, otp, out long _, VerificationWindow.RfcSpecifiedNetworkDelay); + } + + public string GenerateAccessToken(string username) + { + var claims = new[] + { + new Claim(ClaimTypes.Name, username), + new Claim(ClaimTypes.Role, "Admin") + }; + + var jwtKey = configuration["Jwt:Key"]; + if (string.IsNullOrEmpty(jwtKey)) + throw new InvalidOperationException("JWT key is not configured."); + + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey)); + var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + + // Safely read expiry minutes from configuration with a fallback default + var mins = configuration.GetValue("Jwt:AccessTokenExpiryInMinutes") ?? 5; + + var token = new JwtSecurityToken( + issuer: configuration["Jwt:Issuer"], + audience: configuration["Jwt:Audience"], + claims: claims, + expires: DateTime.UtcNow.AddMinutes(mins), + signingCredentials: creds + ); + + return new JwtSecurityTokenHandler().WriteToken(token); + } + + public string GenerateRefreshToken() + { + return Convert.ToBase64String(RandomNumberGenerator.GetBytes(64)); + } + + public async Task SaveRefreshToken(string userEmail, string refreshToken, HttpContext httpContext) + { + var user = await GetUser(userEmail); + if (user == null) throw new InvalidOperationException("User not found."); + + // Store hashed refresh token in DB + var hashedToken = BCrypt.Net.BCrypt.HashPassword(refreshToken); + _context.RefreshTokens.Add(new RefreshToken + { + UserId = user.UserId, + Token = hashedToken, + ExpiryDate = DateTime.UtcNow.AddHours(configuration.GetValue("Jwt:RefreshTokenExpiryInHours", 24)), + JwtId = Guid.NewGuid().ToString(), + DeviceInfo = httpContext.Request.Headers.UserAgent.ToString() + }); + + await _context.SaveChangesAsync(); + } + + public async Task SaveRefreshToken(RefreshToken refreshToken) + { + _context.RefreshTokens.Add(refreshToken); + await _context.SaveChangesAsync(); + } + + public async Task GetRefreshTokenAsync(string refreshToken) + { + // Find user and validate refresh token + var refreshEntity = await _context.RefreshTokens + .Include(rt => rt.User) + .Where(rt => !rt.Revoked && rt.ExpiryDate > DateTime.UtcNow) + .ToListAsync(); + + return refreshEntity.FirstOrDefault(rt => BCrypt.Net.BCrypt.Verify(refreshToken, rt.Token)); + } + + public async Task RemoveRefreshToken(string refreshToken) + { + var tokens = await _context.RefreshTokens + .Where(rt => rt.Revoked == false && rt.ExpiryDate > DateTime.UtcNow) + .ToListAsync(); + + var refreshTokenEntity = tokens + .FirstOrDefault(rt => BCrypt.Net.BCrypt.Verify(refreshToken, rt.Token)); + + if (refreshTokenEntity != null) + { + refreshTokenEntity.Revoked = true; + await _context.SaveChangesAsync(); + } + } + + private async Task GetUser(string userEmail) + { + return await _context.Users.FirstOrDefaultAsync(u => u.Email == userEmail); + } + + private string GenerateOtp(string secretKey) + { + var key = Base32Encoding.ToBytes(secretKey); + var otpExpiryInMinutes = configuration.GetValue("OtpExpiryInMinutes", 3); + var totp = new Totp(key, otpExpiryInMinutes * 60); + return totp.ComputeTotp(DateTime.UtcNow); + } + } +} diff --git a/PortBlog.API/Services/Contracts/IAuthService.cs b/PortBlog.API/Services/Contracts/IAuthService.cs new file mode 100644 index 0000000..acb9e53 --- /dev/null +++ b/PortBlog.API/Services/Contracts/IAuthService.cs @@ -0,0 +1,23 @@ +using PortBlog.API.Entities; + +namespace PortBlog.API.Services.Contracts +{ + public interface IAuthService + { + Task GenerateOtp(string email, CancellationToken ct = default); + + bool ValidateOtp(string secretKey, string otp); + + string GenerateAccessToken(string username); + + string GenerateRefreshToken(); + + Task SaveRefreshToken(string userId, string refreshToken, HttpContext httpContext); + + Task SaveRefreshToken(RefreshToken refreshToken); + + Task GetRefreshTokenAsync(string refreshToken); + + Task RemoveRefreshToken(string refreshToken); + } +} diff --git a/PortBlog.API/Services/Contracts/IOtpService.cs b/PortBlog.API/Services/Contracts/IOtpService.cs new file mode 100644 index 0000000..816bc88 --- /dev/null +++ b/PortBlog.API/Services/Contracts/IOtpService.cs @@ -0,0 +1,6 @@ +namespace PortBlog.API.Services.Contracts +{ + public interface IOtpService + { + } +} diff --git a/PortBlog.API/Services/Contracts/ITemplateService.cs b/PortBlog.API/Services/Contracts/ITemplateService.cs new file mode 100644 index 0000000..1bae10c --- /dev/null +++ b/PortBlog.API/Services/Contracts/ITemplateService.cs @@ -0,0 +1,7 @@ +namespace PortBlog.API.Services.Contracts +{ + public interface ITemplateService + { + Task GetViewTemplate(string viewPath, T model); + } +} diff --git a/PortBlog.API/Services/Contracts/ITokenService.cs b/PortBlog.API/Services/Contracts/ITokenService.cs new file mode 100644 index 0000000..2b9eb42 --- /dev/null +++ b/PortBlog.API/Services/Contracts/ITokenService.cs @@ -0,0 +1,6 @@ +namespace PortBlog.API.Services.Contracts +{ + public interface ITokenService + { + } +} diff --git a/PortBlog.API/Services/Contracts/JwtServicecs.cs b/PortBlog.API/Services/Contracts/JwtServicecs.cs new file mode 100644 index 0000000..93da49e --- /dev/null +++ b/PortBlog.API/Services/Contracts/JwtServicecs.cs @@ -0,0 +1,6 @@ +namespace PortBlog.API.Services.Contracts +{ + public interface JwtServicecs + { + } +} diff --git a/PortBlog.API/Services/JwtService.cs b/PortBlog.API/Services/JwtService.cs new file mode 100644 index 0000000..c8e5e16 --- /dev/null +++ b/PortBlog.API/Services/JwtService.cs @@ -0,0 +1,6 @@ +namespace PortBlog.API.Services +{ + public class JwtService + { + } +} diff --git a/PortBlog.API/Services/MailService.cs b/PortBlog.API/Services/MailService.cs index 220e6a1..906ef50 100644 --- a/PortBlog.API/Services/MailService.cs +++ b/PortBlog.API/Services/MailService.cs @@ -1,5 +1,6 @@ using AutoMapper; -using PortBlog.API.Common; +using KBR.Shared.Mail; +using PortBlog.API.Common.Constants; using PortBlog.API.Entities; using PortBlog.API.Models; using PortBlog.API.Repositories.Contracts; @@ -44,16 +45,17 @@ namespace PortBlog.API.Services client.EnableSsl = true; client.Credentials = new NetworkCredential(mailSettings.Email, mailSettings.Password); - using (var messageMessage = new MailMessage( - from: new MailAddress(messageSendDto.FromEmail), - to: new MailAddress(messageSendDto.ToEmail, messageSendDto.CandidateName) + using (var mailMessage = new MailMessage( + from: new MailAddress(mailSettings.Email), + to: new MailAddress(MailHelpers.ReplaceEmailDomain(messageSendDto.ToEmail, mailSettings.Domain), messageSendDto.Name) )) { - messageMessage.Subject = messageSendDto.Subject; - messageMessage.Body = messageSendDto.Content; + mailMessage.Subject = messageSendDto.Subject; + mailMessage.Body = messageSendDto.Content; + mailMessage.IsBodyHtml = true; - client.Send(messageMessage); + client.Send(mailMessage); messageSendDto.SentStatus = (int)MailConstants.MailStatus.Success; } } diff --git a/PortBlog.API/Services/OtpService.cs b/PortBlog.API/Services/OtpService.cs new file mode 100644 index 0000000..97fcf69 --- /dev/null +++ b/PortBlog.API/Services/OtpService.cs @@ -0,0 +1,6 @@ +namespace PortBlog.API.Services +{ + public class OtpService + { + } +} diff --git a/PortBlog.API/Services/TemplateService.cs b/PortBlog.API/Services/TemplateService.cs new file mode 100644 index 0000000..bb4b03b --- /dev/null +++ b/PortBlog.API/Services/TemplateService.cs @@ -0,0 +1,13 @@ +using PortBlog.API.Services.Contracts; +using Razor.Templating.Core; + +namespace PortBlog.API.Services +{ + public class TemplateService : ITemplateService + { + public async Task GetViewTemplate(string viewPath, T model) + { + return await RazorTemplateEngine.RenderAsync(viewPath, model); + } + } +} diff --git a/PortBlog.API/Services/TokenService.cs b/PortBlog.API/Services/TokenService.cs new file mode 100644 index 0000000..1b9d103 --- /dev/null +++ b/PortBlog.API/Services/TokenService.cs @@ -0,0 +1,6 @@ +namespace PortBlog.API.Services +{ + public class TokenService + { + } +} diff --git a/PortBlog.API/Views/Email/OtpEmailTemplate.cshtml b/PortBlog.API/Views/Email/OtpEmailTemplate.cshtml new file mode 100644 index 0000000..7e4cf00 --- /dev/null +++ b/PortBlog.API/Views/Email/OtpEmailTemplate.cshtml @@ -0,0 +1,67 @@ +@model PortBlog.API.Models.OtpMailModel + + + + + + OTP Verification + + + + +
+

OTP Verification

+

Hello @Model.Name,

+

Your One-Time Password (OTP) for verification is:

+ +
@Model.OtpCode
+ +

This OTP will expire in @Model.ExpiryMinutes minutes.

+

If you did not request this, please ignore this email.

+ +
+ + diff --git a/PortBlog.API/appsettings.Development.json b/PortBlog.API/appsettings.Development.json index ff1f1b7..8598e30 100644 --- a/PortBlog.API/appsettings.Development.json +++ b/PortBlog.API/appsettings.Development.json @@ -4,6 +4,18 @@ "Encryption": "false", "Key": "rgdBsYjrgQV9YaE+6QFK5oyTOWwbl2bSWkuc2JXcIyw=" }, + "Cache": { + "ConnectionString": "SERVER=192.168.0.197; DATABASE=cv_blog; UID=PortBlogDevUser; PWD=p@$$w0rd1234;Allow User Variables=true;", + "Provider": "SqlServer" + }, + "Jwt": { + "Key": "6JSHxgeot3Z1Obwhk4bvY2UoiFyH3tGq1FHXaaMuO5i", + "Issuer": "https://localhost:7013/", + "Audience": "http://localhost:4200", + "AccessTokenExpiryInMinutes": 1, + "RefreshTokenExpiryInHours": 1 + }, + "OTPExpiryInMinutes": 3, "Logging": { "LogLevel": { "Default": "Information", @@ -12,11 +24,12 @@ }, "XApiKey": "c6eAXYcNT873TT7BfMgQyS4ii7hxa53TLEUN7pAGaaU=", "MailSettings": { - "Enable": false, - "Host": "smtp.gmail.com", + "Enable": true, + "Host": "mail.kottedi.in", "Port": 587, - "Email": "", - "Password": "" + "Email": "noreply@kottedi.in", + "Password": "MAINore.4356", + "Domain": "kottedi.in" }, - "AllowedCorsOrigins": "http://localhost:4000,http://127.0.0.1:4000" + "AllowedCorsOrigins": "http://localhost:4200,http://127.0.0.1:4200" } diff --git a/Shared/KBR.Cache/AppDistributedCache.cs b/Shared/KBR.Cache/AppDistributedCache.cs new file mode 100644 index 0000000..c20ee09 --- /dev/null +++ b/Shared/KBR.Cache/AppDistributedCache.cs @@ -0,0 +1,96 @@ + +using KBR.Shared.Cache; +using Microsoft.Extensions.Caching.Distributed; + +namespace KBR.Cache +{ + internal class AppDistributedCache : IAppDistributedCache + { + private readonly IDistributedCache _cache; + private readonly DistributedCacheEntryOptions _entryOptions; + + public AppDistributedCache(IDistributedCache cache) + { + this._cache = cache; + this._entryOptions = new DistributedCacheEntryOptions(); + } + + public T Get(string key) + where T : class + { + if (this._cache.Get(key) is var result && result != null) + { + return result.FromByteArray(); + } + + return default; + } + + public async Task GetAsync(string key, CancellationToken cancellationToken = default) + where T : class + { + var result = await this._cache.GetAsync(key, cancellationToken); + + if (result != null) + { + return result.FromByteArray(); + } + + return default; + } + + public void Set(string key, T obj, DistributedCacheEntryOptions? entryOptions = default) + { + this._cache.Set(key, obj.ToByteArray(), entryOptions ?? this._entryOptions); + } + + public async Task SetAsync(string key, T obj, DistributedCacheEntryOptions? entryOptions = default, CancellationToken cancellationToken = default) + { + await this._cache.SetAsync(key, obj.ToByteArray(), entryOptions ?? this._entryOptions, cancellationToken); + } + + public void Remove(string key) + { + this._cache.Remove(key); + } + + public async Task RemoveAsync(string key, CancellationToken cancellationToken = default) + { + await this._cache.RemoveAsync(key, cancellationToken); + } + + public TItem GetOrCreate(string key, Func factory) + where TItem : class + { + byte[] result = this._cache.Get(key); + var resultData = result?.FromByteArray(); + if (result == null || resultData == null) + { + var data = factory(); + this._cache.Set(key, data.ToByteArray(), this._entryOptions); + return data; + } + + return resultData; + } + + public async Task GetOrCreateAsync(string key, Func> factory, CancellationToken cancellationToken = default) + where TItem : class + { + byte[] result = await this._cache.GetAsync(key, cancellationToken); + var resultData = result?.FromByteArray(); + if (result == null || resultData == null) + { + var data = await factory(); + if (data != null) + { + await this._cache.SetAsync(key, data.ToByteArray(), this._entryOptions, cancellationToken); + } + + return data; + } + + return resultData; + } + } +} diff --git a/Shared/KBR.Cache/CacheHelpers.cs b/Shared/KBR.Cache/CacheHelpers.cs new file mode 100644 index 0000000..d182ed0 --- /dev/null +++ b/Shared/KBR.Cache/CacheHelpers.cs @@ -0,0 +1,24 @@ +using KBR.Shared.Cache.Models; +using Microsoft.Extensions.Caching.Distributed; + +namespace KBR.Cache +{ + public static class CacheHelpers + { + private static readonly string _userOtpSecrets = nameof(_userOtpSecrets); + + private static string UserOtpSecretKey(string key) => $"{_userOtpSecrets}-{key}"; + + public static async Task SetUserSecretsCacheAsync(IAppDistributedCache cache, string userId, string secret, CancellationToken cancellationToken = default) + { + await cache.SetAsync(UserOtpSecretKey(userId), secret, new DistributedCacheEntryOptions { AbsoluteExpiration = DateTime.UtcNow.AddMinutes(3) }, cancellationToken); + } + + public static async Task GetUserOtpSecretAsync(IAppDistributedCache cache, string userId, CancellationToken cancellationToken = default) + { + var key = await cache.GetAsync(UserOtpSecretKey(userId), cancellationToken); + + return key; + } + } +} \ No newline at end of file diff --git a/Shared/KBR.Cache/Constants/CacheProviders.cs b/Shared/KBR.Cache/Constants/CacheProviders.cs new file mode 100644 index 0000000..cc3fb64 --- /dev/null +++ b/Shared/KBR.Cache/Constants/CacheProviders.cs @@ -0,0 +1,11 @@ +namespace KBR.Cache.Constants +{ + public static class CacheProviders + { + public const string InMemory = nameof(InMemory); + + public const string SqlServer = nameof(SqlServer); + + public const string Redis = nameof(Redis); + } +} diff --git a/Shared/KBR.Cache/Extensions/ServiceCollectionExtensions.cs b/Shared/KBR.Cache/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..9233798 --- /dev/null +++ b/Shared/KBR.Cache/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,47 @@ +using KBR.Cache.Constants; +using KBR.Cache.Options; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using System.Diagnostics.CodeAnalysis; + +namespace KBR.Cache.Extensions +{ + public static class ServiceCollectionExtensions + { + public static IServiceCollection AddCache([NotNull] this IServiceCollection services, IConfiguration configuration) + { + // Ensure the 'Microsoft.Extensions.Options.ConfigurationExtensions' package is referenced in your project + var cacheOptions = configuration.GetSection("Cache").Get(); + + if (cacheOptions == null || cacheOptions.Provider == CacheProviders.InMemory) + { + services.AddDistributedMemoryCache(); + } + else if (cacheOptions.Provider == CacheProviders.SqlServer) + { + services.AddDistributedMySqlCache(options => + { + options.ConnectionString = cacheOptions.ConnectionString; + options.TableName = "Cache"; + }); + } + else if (cacheOptions.Provider == CacheProviders.Redis) + { + services.AddStackExchangeRedisCache(options => + { + options.Configuration = cacheOptions.ConnectionString; + options.InstanceName = "SampleInstance"; + }); + } + else + { + throw new Exception("Cache options are not valid"); + } + + services.TryAddSingleton(); + + return services; + } + } +} diff --git a/Shared/KBR.Cache/IAppDistributedCache.cs b/Shared/KBR.Cache/IAppDistributedCache.cs new file mode 100644 index 0000000..9cce8be --- /dev/null +++ b/Shared/KBR.Cache/IAppDistributedCache.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.Caching.Distributed; + +namespace KBR.Cache +{ + public interface IAppDistributedCache + { + T Get(string key) + where T : class; + + Task GetAsync(string key, CancellationToken cancellationToken = default) + where T : class; + + void Remove(string key); + + Task RemoveAsync(string key, CancellationToken cancellationToken = default); + + void Set(string key, T obj, DistributedCacheEntryOptions? options = default); + + Task SetAsync(string key, T obj, DistributedCacheEntryOptions? options = default, CancellationToken cancellationToken = default); + + TItem GetOrCreate(string key, Func factory) + where TItem : class; + + Task GetOrCreateAsync(string key, Func> factory, CancellationToken cancellationToken = default) + where TItem : class; + } +} diff --git a/Shared/KBR.Cache/KBR.Cache.csproj b/Shared/KBR.Cache/KBR.Cache.csproj new file mode 100644 index 0000000..a274065 --- /dev/null +++ b/Shared/KBR.Cache/KBR.Cache.csproj @@ -0,0 +1,26 @@ + + + + net9.0 + enable + enable + + + + + + + + + + + + + + + + + + + + diff --git a/Shared/KBR.Cache/Options/CacheOptions.cs b/Shared/KBR.Cache/Options/CacheOptions.cs new file mode 100644 index 0000000..4f0c502 --- /dev/null +++ b/Shared/KBR.Cache/Options/CacheOptions.cs @@ -0,0 +1,9 @@ +namespace KBR.Cache.Options +{ + public class CacheOptions + { + public string Provider { get; set; } = null!; + + public string? ConnectionString { get; set; } + } +} diff --git a/Shared/KBR.Share.Lite/Extensions/JsonExtensions.cs b/Shared/KBR.Share.Lite/Extensions/JsonExtensions.cs new file mode 100644 index 0000000..550ea5d --- /dev/null +++ b/Shared/KBR.Share.Lite/Extensions/JsonExtensions.cs @@ -0,0 +1,76 @@ +using Newtonsoft.Json; + +namespace KBR.Shared.Lite.Extensions +{ + public static class JsonExtensions + { + public static T? ToObject(string value) + { + return JsonConvert.DeserializeObject(value); + } + + public static T? ToObjectSystemText(string value) + { + return System.Text.Json.JsonSerializer.Deserialize(value); + } + + public static T? ToObject(string value, Type destType) + { + var result = JsonConvert.DeserializeObject(value, destType); + + if (result is null) + { + return default; + } + + return (T)result; + } + + public static object? ToObject(string value, Type destType) + { + return ToObject(value, destType); + } + + public static T? ToObject(string value, JsonConverter[] converters) + { + return JsonConvert.DeserializeObject(value, converters); + } + + public static T? ToObject(string value, Type destType, JsonConverter[] converters) + { + var result = JsonConvert.DeserializeObject(value, destType, converters); + + if (result is null) + { + return default; + } + + return (T)result; + } + + public static string ToJson(T value) + { + return JsonConvert.SerializeObject(value); + } + + public static string ToJsonSystemText(T value) + { + return System.Text.Json.JsonSerializer.Serialize(value); + } + + public static string ToJson(T value, JsonSerializerSettings jsonSerializerSettings) + { + return JsonConvert.SerializeObject(value, jsonSerializerSettings); + } + + public static byte[] ToUtf8Bytes(object obj) + { + return System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(obj); + } + + public static T? ToObject(byte[] utf8Json) + { + return System.Text.Json.JsonSerializer.Deserialize(utf8Json); + } + } +} diff --git a/Shared/KBR.Share.Lite/KBR.Shared.Lite.csproj b/Shared/KBR.Share.Lite/KBR.Shared.Lite.csproj new file mode 100644 index 0000000..2c2f89b --- /dev/null +++ b/Shared/KBR.Share.Lite/KBR.Shared.Lite.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/Shared/KBR.Shared/Cache/CacheExtensions.cs b/Shared/KBR.Shared/Cache/CacheExtensions.cs new file mode 100644 index 0000000..cb08bab --- /dev/null +++ b/Shared/KBR.Shared/Cache/CacheExtensions.cs @@ -0,0 +1,28 @@ +using KBR.Shared.Lite.Extensions; + +namespace KBR.Shared.Cache +{ + public static class CacheExtensions + { + public static byte[] ToByteArray(this object obj) + { + if (obj is not null) + { + return JsonExtensions.ToUtf8Bytes(obj); + } + + return Array.Empty(); + } + + public static T? FromByteArray(this byte[] byteArray) + where T : class + { + if (byteArray is null) + { + return default; + } + + return JsonExtensions.ToObject(byteArray); + } + } +} diff --git a/Shared/KBR.Shared/Cache/CacheHelpers.cs b/Shared/KBR.Shared/Cache/CacheHelpers.cs new file mode 100644 index 0000000..2c009f3 --- /dev/null +++ b/Shared/KBR.Shared/Cache/CacheHelpers.cs @@ -0,0 +1,21 @@ +using KBR.Shared.Cache.Models; +using Microsoft.Extensions.Caching.Distributed; + +namespace KBR.Shared.Cache +{ + public static class CacheHelpers + { + private static readonly string _userSessions = nameof(_userSessions); + private static string UserSessionsKey(string key) => $"{_userSessions}-{key}"; + + public static async Task SetUserSessionsCacheAsync(IAppDistributedCache cache, string userId, UserSessionModel sessions, CancellationToken cancellationToken = default) + { + await cache.SetAsync(UserSessionsKey(userId), sessions, GetOptions(), cancellationToken); + } + + private static DistributedCacheEntryOptions GetOptions() + { + return new DistributedCacheEntryOptions { AbsoluteExpiration = DateTime.MaxValue }; + } + } +} \ No newline at end of file diff --git a/Shared/KBR.Shared/Cache/IAppDistributedCache.cs b/Shared/KBR.Shared/Cache/IAppDistributedCache.cs new file mode 100644 index 0000000..d7dd61d --- /dev/null +++ b/Shared/KBR.Shared/Cache/IAppDistributedCache.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.Caching.Distributed; + +namespace KBR.Shared.Cache +{ + public interface IAppDistributedCache + { + T Get(string key) + where T : class; + + Task GetAsync(string key, CancellationToken cancellationToken = default) + where T : class; + + void Remove(string key); + + Task RemoveAsync(string key, CancellationToken cancellationToken = default); + + void Set(string key, T obj, DistributedCacheEntryOptions? options = default); + + Task SetAsync(string key, T obj, DistributedCacheEntryOptions? options = default, CancellationToken cancellationToken = default); + + TItem GetOrCreate(string key, Func factory) + where TItem : class; + + Task GetOrCreateAsync(string key, Func> factory, CancellationToken cancellationToken = default) + where TItem : class; + } +} diff --git a/Shared/KBR.Shared/Cache/Models/UserSessionModel.cs b/Shared/KBR.Shared/Cache/Models/UserSessionModel.cs new file mode 100644 index 0000000..4375574 --- /dev/null +++ b/Shared/KBR.Shared/Cache/Models/UserSessionModel.cs @@ -0,0 +1,15 @@ +namespace KBR.Shared.Cache.Models +{ + public class UserSessionModel + { + public UserSessionModel() + { + Alive = new(); + Killed = new(); + } + + public List Alive { get; set; } + + public List Killed { get; set; } + } +} diff --git a/Shared/KBR.Shared/KBR.Shared.csproj b/Shared/KBR.Shared/KBR.Shared.csproj new file mode 100644 index 0000000..99ed569 --- /dev/null +++ b/Shared/KBR.Shared/KBR.Shared.csproj @@ -0,0 +1,17 @@ + + + + net9.0 + enable + enable + + + + + + + + + + + diff --git a/Shared/KBR.Shared/Mail/MailHelpers.cs b/Shared/KBR.Shared/Mail/MailHelpers.cs new file mode 100644 index 0000000..4d32970 --- /dev/null +++ b/Shared/KBR.Shared/Mail/MailHelpers.cs @@ -0,0 +1,21 @@ +namespace KBR.Shared.Mail +{ + public static class MailHelpers + { + // Replace email with other domain passed as a parameter + public static string ReplaceEmailDomain(string email, string newDomain) + { + if (string.IsNullOrWhiteSpace(email)) + throw new ArgumentException("Email cannot be null or empty.", nameof(email)); + + if (string.IsNullOrWhiteSpace(newDomain)) + throw new ArgumentException("New domain cannot be null or empty.", nameof(newDomain)); + + var atIndex = email.IndexOf('@'); + if (atIndex == -1) + throw new ArgumentException("Invalid email format.", nameof(email)); + + return $"{email.Substring(0, atIndex + 1)}{newDomain}"; + } + } +} From cd01c11be795467915321fe1a942a0a7f51cfd17 Mon Sep 17 00:00:00 2001 From: Bangara Raju Kottedi Date: Sat, 22 Nov 2025 14:16:31 +0530 Subject: [PATCH 2/5] Refactor controllers and services; update logging Refactored AdminController and AuthService to use primary constructor syntax, removing explicit field declarations. Updated logging to use structured logging across controllers and services. Added XML documentation for methods in AdminController, AuthController, AuthService, and MailService. Modified Program.cs to improve connection string handling and Swagger setup. Removed deprecated service files. --- PortBlog.API/Controllers/AdminController.cs | 58 +++--- PortBlog.API/Controllers/AuthController.cs | 22 +- PortBlog.API/PortBlog.API.xml | 194 +++++++++++++++++- PortBlog.API/Program.cs | 45 ++-- PortBlog.API/Services/AuthService.cs | 80 +++++--- .../Services/Contracts/IAuthService.cs | 45 +++- .../Services/Contracts/IOtpService.cs | 6 - .../Services/Contracts/ITokenService.cs | 6 - .../Services/Contracts/JwtServicecs.cs | 6 - PortBlog.API/Services/JwtService.cs | 6 - PortBlog.API/Services/MailService.cs | 66 +++--- PortBlog.API/Services/OtpService.cs | 6 - PortBlog.API/Services/TemplateService.cs | 10 + PortBlog.API/Services/TokenService.cs | 6 - 14 files changed, 395 insertions(+), 161 deletions(-) delete mode 100644 PortBlog.API/Services/Contracts/IOtpService.cs delete mode 100644 PortBlog.API/Services/Contracts/ITokenService.cs delete mode 100644 PortBlog.API/Services/Contracts/JwtServicecs.cs delete mode 100644 PortBlog.API/Services/JwtService.cs delete mode 100644 PortBlog.API/Services/OtpService.cs delete mode 100644 PortBlog.API/Services/TokenService.cs diff --git a/PortBlog.API/Controllers/AdminController.cs b/PortBlog.API/Controllers/AdminController.cs index 56905bf..b6cb275 100644 --- a/PortBlog.API/Controllers/AdminController.cs +++ b/PortBlog.API/Controllers/AdminController.cs @@ -4,27 +4,19 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using PortBlog.API.Models; using PortBlog.API.Repositories.Contracts; -using PortBlog.API.Services.Contracts; namespace PortBlog.API.Controllers { + + /// + /// Controller for administrative actions related to candidates and their resumes. + /// [Route("api/v{version:apiVersion}/admin")] [ApiController] [ApiVersion(1)] [Authorize] - public class AdminController : Controller + public class AdminController(ILogger logger, ICandidateRepository candidateRepository, IResumeRepository resumeRepository, IMapper mapper) : Controller { - private readonly ILogger _logger; - private readonly ICandidateRepository _candidateRepository; - private readonly IResumeRepository _resumeRepository; - private readonly IMapper _mapper; - public AdminController(ILogger logger, ICandidateRepository candidateRepository, IResumeRepository resumeRepository, IMailService mailService, IMapper mapper, IMailRepository mailRepository) - { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _candidateRepository = candidateRepository ?? throw new ArgumentNullException(nameof(candidateRepository)); - _resumeRepository = resumeRepository ?? throw new ArgumentNullException(nameof(resumeRepository)); - _mapper = mapper; - } /// /// Get hobbies of the candidate by candidateid /// @@ -40,20 +32,20 @@ namespace PortBlog.API.Controllers { try { - if (!await _candidateRepository.CandidateExistAsync(candidateId)) + if (!await candidateRepository.CandidateExistAsync(candidateId)) { - _logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching about details."); + logger.LogInformation("Candidate with id {CandidateId} wasn't found when fetching about details.", candidateId); return NotFound(); } - var aboutDetails = await _resumeRepository.GetHobbiesAsync(candidateId); + var aboutDetails = await resumeRepository.GetHobbiesAsync(candidateId); - return Ok(_mapper.Map(aboutDetails)); + return Ok(mapper.Map(aboutDetails)); } catch (Exception ex) { - _logger.LogCritical($"Exception while getting about details for the candidate with id {candidateId}.", ex); + logger.LogCritical(ex, "Exception while getting about details for the candidate with id {CandidateId}.", candidateId); return StatusCode(500, "A problem happened while handling your request."); } } @@ -73,20 +65,20 @@ namespace PortBlog.API.Controllers { try { - if (!await _candidateRepository.CandidateExistAsync(candidateId)) + if (!await candidateRepository.CandidateExistAsync(candidateId)) { - _logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching candidate with social links."); + logger.LogInformation("Candidate with id {CandidateId} wasn't found when fetching candidate with social links.", candidateId); return NotFound(); } - var contact = await _resumeRepository.GetCandidateWithSocialLinksAsync(candidateId); + var contact = await resumeRepository.GetCandidateWithSocialLinksAsync(candidateId); - return Ok(_mapper.Map(contact)); + return Ok(mapper.Map(contact)); } catch (Exception ex) { - _logger.LogCritical($"Exception while getting contact for the candidate with social links with id {candidateId}.", ex); + logger.LogCritical(ex, "Exception while getting contact for the candidate with social links with id {CandidateId}.", candidateId); return StatusCode(500, "A problem happened while handling your request."); } } @@ -106,20 +98,20 @@ namespace PortBlog.API.Controllers { try { - if (!await _candidateRepository.CandidateExistAsync(candidateId)) + if (!await candidateRepository.CandidateExistAsync(candidateId)) { - _logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching resume."); + logger.LogInformation("Candidate with id {CandidateId} wasn't found when fetching resume.", candidateId); return NotFound(); } - var resume = await _resumeRepository.GetResumeAsync(candidateId); + var resume = await resumeRepository.GetResumeAsync(candidateId); - return Ok(_mapper.Map(resume)); + return Ok(mapper.Map(resume)); } catch (Exception ex) { - _logger.LogCritical($"Exception while getting resume for the candidate with id {candidateId}.", ex); + logger.LogCritical(ex, "Exception while getting resume for the candidate with id {CandidateId}.", candidateId); return StatusCode(500, "A problem happened while handling your request."); } } @@ -139,20 +131,20 @@ namespace PortBlog.API.Controllers { try { - if (!await _candidateRepository.CandidateExistAsync(candidateId)) + if (!await candidateRepository.CandidateExistAsync(candidateId)) { - _logger.LogInformation($"Candidate with id {candidateId} wasn't found when fetching projects."); + logger.LogInformation("Candidate with id {CandidateId} wasn't found when fetching projects.", candidateId); return NotFound(); } - var projects = await _resumeRepository.GetProjectsAsync(candidateId); + var projects = await resumeRepository.GetProjectsAsync(candidateId); - return Ok(_mapper.Map(projects)); + return Ok(mapper.Map(projects)); } catch (Exception ex) { - _logger.LogCritical($"Exception while getting projects for the candidate with id {candidateId}.", ex); + logger.LogCritical(ex, "Exception while getting projects for the candidate with id {CandidateId}.", candidateId); return StatusCode(500, "A problem happened while handling your request."); } } diff --git a/PortBlog.API/Controllers/AuthController.cs b/PortBlog.API/Controllers/AuthController.cs index f2d5983..d1bf7dd 100644 --- a/PortBlog.API/Controllers/AuthController.cs +++ b/PortBlog.API/Controllers/AuthController.cs @@ -1,15 +1,11 @@ using Asp.Versioning; using AutoMapper; -using Azure.Core; using KBR.Cache; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; using PortBlog.API.Entities; using PortBlog.API.Models; using PortBlog.API.Repositories.Contracts; -using PortBlog.API.Services; using PortBlog.API.Services.Contracts; -using System.Threading.Tasks; namespace PortBlog.API.Controllers { @@ -24,7 +20,7 @@ namespace PortBlog.API.Controllers /// /// Generates a One-Time Password (OTP) for the specified candidate and sends it via email. /// - /// The ID of the candidate for whom the OTP is generated. + /// The email of the candidate for whom the OTP is generated. /// An ActionResult indicating the result of the operation. [HttpPost("GenerateOtp")] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -38,7 +34,7 @@ namespace PortBlog.API.Controllers var candidate = await candidateRepository.GetCandidateAsync(email); if (candidate == null) { - logger.LogInformation($"Candidate with email ({email}) wasn't found."); + logger.LogInformation("Candidate with email ({Email}) wasn't found.", email); return NotFound(); } @@ -62,7 +58,7 @@ namespace PortBlog.API.Controllers } catch (Exception ex) { - logger.LogCritical($"Exception while sending OTP for {messageSendDto.ToEmail}.", ex); + logger.LogCritical(ex, "Exception while sending OTP for {ToEmail}.", messageSendDto.ToEmail); return StatusCode(500, "A problem happened while handling your request."); } } @@ -108,11 +104,15 @@ namespace PortBlog.API.Controllers } catch (Exception ex) { - logger.LogCritical($"Exception while validating OTP for {request.UserId}.", ex); + logger.LogCritical(ex, "Exception while validating OTP for {UserId}.", request?.UserId); return StatusCode(500, "A problem happened while handling your request."); } } + /// + /// Refreshes the access token using a valid refresh token from the HttpOnly cookie. + /// + /// An IActionResult containing the new access token if the refresh token is valid; otherwise, an appropriate error response. [HttpPost("RefreshToken")] public async Task Refresh() { @@ -120,7 +120,7 @@ namespace PortBlog.API.Controllers if (!Request.Cookies.TryGetValue("refreshToken", out var refreshToken)) return Unauthorized(); - var matchedToken = await authService.GetRefreshTokenAsync(refreshToken); + var matchedToken = await authService.GetRefreshToken(refreshToken); if (matchedToken == null) return Forbid(); // Rotate refresh token @@ -147,6 +147,10 @@ namespace PortBlog.API.Controllers return Ok(new { accessToken = newAccessToken }); } + /// + /// Logs out the current user by removing the refresh token cookie and invalidating the refresh token. + /// + /// An IActionResult indicating the result of the logout operation. [HttpPost("logout")] public async Task Logout() { diff --git a/PortBlog.API/PortBlog.API.xml b/PortBlog.API/PortBlog.API.xml index 0bd7480..274a32b 100644 --- a/PortBlog.API/PortBlog.API.xml +++ b/PortBlog.API/PortBlog.API.xml @@ -4,6 +4,16 @@ PortBlog.API + + + Controller for administrative actions related to candidates and their resumes. + + + + + Controller for administrative actions related to candidates and their resumes. + + Get hobbies of the candidate by candidateid @@ -50,7 +60,7 @@ Generates a One-Time Password (OTP) for the specified candidate and sends it via email. - The ID of the candidate for whom the OTP is generated. + The email of the candidate for whom the OTP is generated. An ActionResult indicating the result of the operation. @@ -60,6 +70,18 @@ The request containing the user ID and OTP code to verify. An ActionResult indicating the result of the verification. + + + Refreshes the access token using a valid refresh token from the HttpOnly cookie. + + An IActionResult containing the new access token if the refresh token is valid; otherwise, an appropriate error response. + + + + Logs out the current user by removing the refresh token cookie and invalidating the refresh token. + + An IActionResult indicating the result of the logout operation. + Get CV details of the candidate by candidateid. @@ -399,6 +421,24 @@ The work experiences of the candidate + + + Provides authentication services such as OTP generation, validation, and JWT token management. + + + + + Provides authentication services such as OTP generation, validation, and JWT token management. + + + + + Generates a one-time password (OTP) for the specified email address and stores the secret key in the cache. + + The email address for which to generate the OTP. + A cancellation token that can be used to cancel the operation. + A task that represents the asynchronous operation. The task result contains the generated OTP as a string. + Validates the provided OTP against the secret key. @@ -407,5 +447,157 @@ The OTP to validate. True if the OTP is valid; otherwise, false. + + + Generates a JWT access token for the specified username. + + The username for which to generate the access token. + The generated JWT access token as a string. + + + + Generates a secure random refresh token as a Base64-encoded string. + + The generated refresh token. + + + + Saves a refresh token for the specified user email and associates it with the current HTTP context. + + The email address of the user. + The refresh token to be saved. + The current HTTP context containing request information. + A task that represents the asynchronous save operation. + + + + Saves a refresh token entity to the database. + + The refresh token entity to save. + A task that represents the asynchronous save operation. + + + + Retrieves a valid, non-revoked, and non-expired refresh token entity matching the provided refresh token string. + + The refresh token string to validate and retrieve. + + A task that represents the asynchronous operation. The task result contains the matching entity if found and valid; otherwise, throws . + + Thrown if no valid refresh token is found. + + + + Revokes (removes) a refresh token by marking it as revoked in the database if it is valid and not expired. + + The refresh token to revoke. + A task that represents the asynchronous revoke operation. + + + + Provides authentication-related services such as OTP generation, token management, and refresh token handling. + + + + + Generates a one-time password (OTP) for the specified email. + + The email address to generate the OTP for. + A cancellation token. + The generated OTP as a string. + + + + Validates the provided OTP against the secret key. + + The secret key used for validation. + The OTP to validate. + True if the OTP is valid; otherwise, false. + + + + Generates an access token for the specified username. + + The username for which to generate the access token. + The generated access token as a string. + + + + Generates a new refresh token. + + The generated refresh token as a string. + + + + Saves the refresh token for the specified user and HTTP context. + + The user ID. + The refresh token to save. + The HTTP context. + + + + Saves the specified refresh token. + + The refresh token entity to save. + + + + Retrieves the refresh token entity for the specified token string. + + The refresh token string. + The corresponding entity. + + + + Removes the specified refresh token. + + The refresh token to remove. + + + + Provides functionality for sending emails and logging message activity. + + + Initializes a new instance of the class. + + The application configuration. + The logger instance. + The mail repository for storing messages. + The AutoMapper instance. + + + + Provides functionality for sending emails and logging message activity. + + + Initializes a new instance of the class. + + The application configuration. + The logger instance. + The mail repository for storing messages. + The AutoMapper instance. + + + + Sends an email message asynchronously using the provided message details. + + The message details to send. + A task representing the asynchronous operation. + + + + Provides functionality to render Razor view templates with a specified model. + + + + + Renders a Razor view template at the specified path using the provided model. + + The type of the model to pass to the view. + The path to the Razor view template. + The model to use when rendering the view. + A task that represents the asynchronous operation. The task result contains the rendered view as a string. + diff --git a/PortBlog.API/Program.cs b/PortBlog.API/Program.cs index ac46b28..9d9e7d0 100644 --- a/PortBlog.API/Program.cs +++ b/PortBlog.API/Program.cs @@ -43,7 +43,7 @@ if (!string.IsNullOrEmpty(urls.Value)) } var allowedCorsOrigins = builder.Configuration.GetSection("AllowedCorsOrigins"); -string[] origins = Array.Empty(); +string[] origins = []; if (!String.IsNullOrEmpty(allowedCorsOrigins.Value)) { @@ -78,16 +78,16 @@ builder.Services.AddEndpointsApiExplorer(); var connectionString = builder.Configuration.GetConnectionString("PortBlogDBConnectionString"); -if (builder.Configuration.GetValue("ConnectionStrings:Encryption")) -{ - connectionString = builder.Configuration.DecryptConnectionString(connectionString); -} - if (string.IsNullOrEmpty(connectionString)) { throw new Exception("Connection string cannot be empty"); } +if (builder.Configuration.GetValue("ConnectionStrings:Encryption")) +{ + connectionString = builder.Configuration.DecryptConnectionString(connectionString); +} + builder.Services .AddDbContext(dbContextOptions => dbContextOptions.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))); @@ -111,23 +111,8 @@ builder.Services.AddApiVersioning(setupAction => setupAction.SubstituteApiVersionInUrl = true; }); -var apiVersionDescriptionProvider = builder.Services.BuildServiceProvider() - .GetRequiredService(); - builder.Services.AddSwaggerGen(c => { - foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions) - { - c.SwaggerDoc( - $"{description.GroupName}", - new() - { - Title = "Portfolio Blog API", - Version = description.ApiVersion.ToString(), - Description = "Through this API you can access candidate cv details and along with other details." - }); - } - // XML Comments file for API Documentation var xmlCommentsFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlCommentsFullPath = $"{Path.Combine(AppContext.BaseDirectory, xmlCommentsFile)}"; @@ -174,16 +159,21 @@ builder.Services.AddSwaggerGen(c => } }; - var requirement = new OpenApiSecurityRequirement() + var requirement = new OpenApiSecurityRequirement { - {key, new List {} }, - {bearerScheme, new List{} } + { key, new List() }, + { bearerScheme, new List() } }; c.AddSecurityRequirement(requirement); }); -var key = Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]); +var jwtKey = builder.Configuration["Jwt:Key"]; +if (string.IsNullOrEmpty(jwtKey)) +{ + throw new Exception("JWT key cannot be null or empty. Please check your configuration."); +} +var key = Encoding.UTF8.GetBytes(jwtKey); builder.Services.AddAuthentication(options => { @@ -219,8 +209,9 @@ if (app.Environment.IsDevelopment()) app.UseSwagger(); app.UseSwaggerUI(setupAction => { - var descriptions = app.DescribeApiVersions(); - foreach (var description in descriptions) + // Get the IApiVersionDescriptionProvider from the app's service provider + var apiVersionDescriptionProvider = app.Services.GetRequiredService(); + foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions) { setupAction.SwaggerEndpoint( $"/swagger/{description.GroupName}/swagger.json", diff --git a/PortBlog.API/Services/AuthService.cs b/PortBlog.API/Services/AuthService.cs index 998c57d..ae97e58 100644 --- a/PortBlog.API/Services/AuthService.cs +++ b/PortBlog.API/Services/AuthService.cs @@ -12,19 +12,17 @@ using System.Text; namespace PortBlog.API.Services { - public class AuthService : IAuthService + /// + /// Provides authentication services such as OTP generation, validation, and JWT token management. + /// + public class AuthService(IConfiguration configuration, IAppDistributedCache cache, CvBlogContext context) : IAuthService { - private readonly IConfiguration configuration; - private readonly IAppDistributedCache cache; - private readonly CvBlogContext _context; - - public AuthService(IConfiguration configuration, IAppDistributedCache cache, CvBlogContext context) - { - this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); - this.cache = cache ?? throw new ArgumentNullException(nameof(cache)); - this._context = context ?? throw new ArgumentNullException(nameof(context)); - } - + /// + /// Generates a one-time password (OTP) for the specified email address and stores the secret key in the cache. + /// + /// The email address for which to generate the OTP. + /// A cancellation token that can be used to cancel the operation. + /// A task that represents the asynchronous operation. The task result contains the generated OTP as a string. public async Task GenerateOtp(string email, CancellationToken ct = default) { var secretKey = KeyGeneration.GenerateRandomKey(20); @@ -51,6 +49,11 @@ namespace PortBlog.API.Services return totp.VerifyTotp(DateTime.UtcNow, otp, out long _, VerificationWindow.RfcSpecifiedNetworkDelay); } + /// + /// Generates a JWT access token for the specified username. + /// + /// The username for which to generate the access token. + /// The generated JWT access token as a string. public string GenerateAccessToken(string username) { var claims = new[] @@ -80,19 +83,29 @@ namespace PortBlog.API.Services return new JwtSecurityTokenHandler().WriteToken(token); } + /// + /// Generates a secure random refresh token as a Base64-encoded string. + /// + /// The generated refresh token. public string GenerateRefreshToken() { return Convert.ToBase64String(RandomNumberGenerator.GetBytes(64)); } + /// + /// Saves a refresh token for the specified user email and associates it with the current HTTP context. + /// + /// The email address of the user. + /// The refresh token to be saved. + /// The current HTTP context containing request information. + /// A task that represents the asynchronous save operation. public async Task SaveRefreshToken(string userEmail, string refreshToken, HttpContext httpContext) { - var user = await GetUser(userEmail); - if (user == null) throw new InvalidOperationException("User not found."); + var user = await GetUser(userEmail) ?? throw new InvalidOperationException("User not found."); // Store hashed refresh token in DB var hashedToken = BCrypt.Net.BCrypt.HashPassword(refreshToken); - _context.RefreshTokens.Add(new RefreshToken + context.RefreshTokens.Add(new RefreshToken { UserId = user.UserId, Token = hashedToken, @@ -101,29 +114,48 @@ namespace PortBlog.API.Services DeviceInfo = httpContext.Request.Headers.UserAgent.ToString() }); - await _context.SaveChangesAsync(); + await context.SaveChangesAsync(); } + /// + /// Saves a refresh token entity to the database. + /// + /// The refresh token entity to save. + /// A task that represents the asynchronous save operation. public async Task SaveRefreshToken(RefreshToken refreshToken) { - _context.RefreshTokens.Add(refreshToken); - await _context.SaveChangesAsync(); + context.RefreshTokens.Add(refreshToken); + await context.SaveChangesAsync(); } - public async Task GetRefreshTokenAsync(string refreshToken) + /// + /// Retrieves a valid, non-revoked, and non-expired refresh token entity matching the provided refresh token string. + /// + /// The refresh token string to validate and retrieve. + /// + /// A task that represents the asynchronous operation. The task result contains the matching entity if found and valid; otherwise, throws . + /// + /// Thrown if no valid refresh token is found. + public async Task GetRefreshToken(string refreshToken) { // Find user and validate refresh token - var refreshEntity = await _context.RefreshTokens + var refreshEntity = await context.RefreshTokens .Include(rt => rt.User) .Where(rt => !rt.Revoked && rt.ExpiryDate > DateTime.UtcNow) .ToListAsync(); - return refreshEntity.FirstOrDefault(rt => BCrypt.Net.BCrypt.Verify(refreshToken, rt.Token)); + var token = refreshEntity.FirstOrDefault(rt => BCrypt.Net.BCrypt.Verify(refreshToken, rt.Token)) ?? throw new InvalidOperationException("Refresh token not found or invalid."); + return token; } + /// + /// Revokes (removes) a refresh token by marking it as revoked in the database if it is valid and not expired. + /// + /// The refresh token to revoke. + /// A task that represents the asynchronous revoke operation. public async Task RemoveRefreshToken(string refreshToken) { - var tokens = await _context.RefreshTokens + var tokens = await context.RefreshTokens .Where(rt => rt.Revoked == false && rt.ExpiryDate > DateTime.UtcNow) .ToListAsync(); @@ -133,13 +165,13 @@ namespace PortBlog.API.Services if (refreshTokenEntity != null) { refreshTokenEntity.Revoked = true; - await _context.SaveChangesAsync(); + await context.SaveChangesAsync(); } } private async Task GetUser(string userEmail) { - return await _context.Users.FirstOrDefaultAsync(u => u.Email == userEmail); + return await context.Users.FirstOrDefaultAsync(u => u.Email == userEmail); } private string GenerateOtp(string secretKey) diff --git a/PortBlog.API/Services/Contracts/IAuthService.cs b/PortBlog.API/Services/Contracts/IAuthService.cs index acb9e53..f18645e 100644 --- a/PortBlog.API/Services/Contracts/IAuthService.cs +++ b/PortBlog.API/Services/Contracts/IAuthService.cs @@ -2,22 +2,65 @@ namespace PortBlog.API.Services.Contracts { + /// + /// Provides authentication-related services such as OTP generation, token management, and refresh token handling. + /// public interface IAuthService { + /// + /// Generates a one-time password (OTP) for the specified email. + /// + /// The email address to generate the OTP for. + /// A cancellation token. + /// The generated OTP as a string. Task GenerateOtp(string email, CancellationToken ct = default); + /// + /// Validates the provided OTP against the secret key. + /// + /// The secret key used for validation. + /// The OTP to validate. + /// True if the OTP is valid; otherwise, false. bool ValidateOtp(string secretKey, string otp); + /// + /// Generates an access token for the specified username. + /// + /// The username for which to generate the access token. + /// The generated access token as a string. string GenerateAccessToken(string username); + /// + /// Generates a new refresh token. + /// + /// The generated refresh token as a string. string GenerateRefreshToken(); + /// + /// Saves the refresh token for the specified user and HTTP context. + /// + /// The user ID. + /// The refresh token to save. + /// The HTTP context. Task SaveRefreshToken(string userId, string refreshToken, HttpContext httpContext); + /// + /// Saves the specified refresh token. + /// + /// The refresh token entity to save. Task SaveRefreshToken(RefreshToken refreshToken); - Task GetRefreshTokenAsync(string refreshToken); + /// + /// Retrieves the refresh token entity for the specified token string. + /// + /// The refresh token string. + /// The corresponding entity. + Task GetRefreshToken(string refreshToken); + /// + /// Removes the specified refresh token. + /// + /// The refresh token to remove. Task RemoveRefreshToken(string refreshToken); } } diff --git a/PortBlog.API/Services/Contracts/IOtpService.cs b/PortBlog.API/Services/Contracts/IOtpService.cs deleted file mode 100644 index 816bc88..0000000 --- a/PortBlog.API/Services/Contracts/IOtpService.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace PortBlog.API.Services.Contracts -{ - public interface IOtpService - { - } -} diff --git a/PortBlog.API/Services/Contracts/ITokenService.cs b/PortBlog.API/Services/Contracts/ITokenService.cs deleted file mode 100644 index 2b9eb42..0000000 --- a/PortBlog.API/Services/Contracts/ITokenService.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace PortBlog.API.Services.Contracts -{ - public interface ITokenService - { - } -} diff --git a/PortBlog.API/Services/Contracts/JwtServicecs.cs b/PortBlog.API/Services/Contracts/JwtServicecs.cs deleted file mode 100644 index 93da49e..0000000 --- a/PortBlog.API/Services/Contracts/JwtServicecs.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace PortBlog.API.Services.Contracts -{ - public interface JwtServicecs - { - } -} diff --git a/PortBlog.API/Services/JwtService.cs b/PortBlog.API/Services/JwtService.cs deleted file mode 100644 index c8e5e16..0000000 --- a/PortBlog.API/Services/JwtService.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace PortBlog.API.Services -{ - public class JwtService - { - } -} diff --git a/PortBlog.API/Services/MailService.cs b/PortBlog.API/Services/MailService.cs index 906ef50..3cf85db 100644 --- a/PortBlog.API/Services/MailService.cs +++ b/PortBlog.API/Services/MailService.cs @@ -10,29 +10,32 @@ using System.Net.Mail; namespace PortBlog.API.Services { - public class MailService : IMailService + /// + /// Provides functionality for sending emails and logging message activity. + /// + /// + /// Initializes a new instance of the class. + /// + /// The application configuration. + /// The logger instance. + /// The mail repository for storing messages. + /// The AutoMapper instance. + public class MailService(IConfiguration configuration, ILogger logger, IMailRepository mailRepository, IMapper mapper) : IMailService { - private readonly ILogger _logger; - private readonly IConfiguration _configuration; - private readonly IMailRepository _mailRepository; - private readonly IMapper _mapper; - - public MailService(IConfiguration configuration, ILogger logger, IMailRepository mailRepository, IMapper mapper) - { - _logger = logger; - _configuration = configuration; - _mailRepository = mailRepository; - _mapper = mapper; - } + /// + /// Sends an email message asynchronously using the provided message details. + /// + /// The message details to send. + /// A task representing the asynchronous operation. public async Task SendAsync(MessageSendDto messageSendDto) { - _logger.LogInformation($"Sending message from {messageSendDto.Name} ({messageSendDto.FromEmail})."); + logger.LogInformation("Sending message from {Name} ({FromEmail}).", messageSendDto.Name, messageSendDto.FromEmail); messageSendDto.Subject = $"Message from {messageSendDto.Name}: Portfolio"; - var messageEntity = _mapper.Map(messageSendDto); + var messageEntity = mapper.Map(messageSendDto); try { - var mailSettings = _configuration.GetSection("MailSettings").Get(); + var mailSettings = configuration.GetSection("MailSettings").Get(); if (mailSettings != null && mailSettings.Enable) { @@ -45,31 +48,34 @@ namespace PortBlog.API.Services client.EnableSsl = true; client.Credentials = new NetworkCredential(mailSettings.Email, mailSettings.Password); - using (var mailMessage = new MailMessage( + using var mailMessage = new MailMessage( from: new MailAddress(mailSettings.Email), to: new MailAddress(MailHelpers.ReplaceEmailDomain(messageSendDto.ToEmail, mailSettings.Domain), messageSendDto.Name) - )) - { + ); - mailMessage.Subject = messageSendDto.Subject; - mailMessage.Body = messageSendDto.Content; - mailMessage.IsBodyHtml = true; + mailMessage.Subject = messageSendDto.Subject; + mailMessage.Body = messageSendDto.Content; + mailMessage.IsBodyHtml = true; - client.Send(mailMessage); - messageSendDto.SentStatus = (int)MailConstants.MailStatus.Success; - } + client.Send(mailMessage); + messageSendDto.SentStatus = (int)MailConstants.MailStatus.Success; } - _mailRepository.AddMessage(messageEntity); - await _mailRepository.SaveChangesAsync(); + mailRepository.AddMessage(messageEntity); + await mailRepository.SaveChangesAsync(); } } catch (Exception ex) { - _logger.LogCritical($"Exception while sending mail from {new MailAddress(messageSendDto.FromEmail, messageSendDto.Name)}", ex); + logger.LogCritical( + "Exception while sending mail from {FromEmail} ({Name}): {Exception}", + messageSendDto.FromEmail, + messageSendDto.Name, + ex.Message + ); messageSendDto.SentStatus = (int)MailConstants.MailStatus.Failed; - _mailRepository.AddMessage(messageEntity); - await _mailRepository.SaveChangesAsync(); + mailRepository.AddMessage(messageEntity); + await mailRepository.SaveChangesAsync(); throw new Exception(); } } diff --git a/PortBlog.API/Services/OtpService.cs b/PortBlog.API/Services/OtpService.cs deleted file mode 100644 index 97fcf69..0000000 --- a/PortBlog.API/Services/OtpService.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace PortBlog.API.Services -{ - public class OtpService - { - } -} diff --git a/PortBlog.API/Services/TemplateService.cs b/PortBlog.API/Services/TemplateService.cs index bb4b03b..60e8cd8 100644 --- a/PortBlog.API/Services/TemplateService.cs +++ b/PortBlog.API/Services/TemplateService.cs @@ -3,8 +3,18 @@ using Razor.Templating.Core; namespace PortBlog.API.Services { + /// + /// Provides functionality to render Razor view templates with a specified model. + /// public class TemplateService : ITemplateService { + /// + /// Renders a Razor view template at the specified path using the provided model. + /// + /// The type of the model to pass to the view. + /// The path to the Razor view template. + /// The model to use when rendering the view. + /// A task that represents the asynchronous operation. The task result contains the rendered view as a string. public async Task GetViewTemplate(string viewPath, T model) { return await RazorTemplateEngine.RenderAsync(viewPath, model); diff --git a/PortBlog.API/Services/TokenService.cs b/PortBlog.API/Services/TokenService.cs deleted file mode 100644 index 1b9d103..0000000 --- a/PortBlog.API/Services/TokenService.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace PortBlog.API.Services -{ - public class TokenService - { - } -} From 5b7952877e204bc49f0d04b352753a709d017b77 Mon Sep 17 00:00:00 2001 From: Bangara Raju Kottedi Date: Sun, 15 Feb 2026 05:27:35 +0530 Subject: [PATCH 3/5] Admin API refactor: claim-based resume CRUD & versioning Major refactor of AdminController and related services to support full CRUD for candidate resume, projects, hobbies, skills, academics, experiences, certifications, and contact info, all using access token claims for candidate identity. Introduced AdminService and expanded IResumeRepository for granular entity management. Updated DTOs for upsert operations and date support. Improved API versioning (Asp.Versioning.Mvc), Swagger integration, and middleware setup. Added unit test project. Enhanced error handling, documentation, and mapping. --- PortBlog.API.sln | 62 +- PortBlog.API/Controllers/AdminController.cs | 422 ++++++++++--- PortBlog.API/Controllers/AuthController.cs | 4 +- PortBlog.API/Controllers/BlogController.cs | 2 +- PortBlog.API/Controllers/CvController.cs | 6 +- PortBlog.API/Controllers/PostController.cs | 6 +- .../Extensions/ConfigureSwaggerOptions.cs | 28 + PortBlog.API/Extensions/ServiceExtensions.cs | 1 + PortBlog.API/Models/AcademicDto.cs | 2 +- PortBlog.API/Models/CertificationDto.cs | 2 +- PortBlog.API/Models/ExperienceDetailsDto.cs | 2 +- PortBlog.API/Models/ExperienceDto.cs | 23 +- PortBlog.API/Models/HobbyDto.cs | 2 +- PortBlog.API/Models/ProjectDto.cs | 2 +- PortBlog.API/Models/SkillDto.cs | 2 +- PortBlog.API/PortBlog.API.csproj | 1 + PortBlog.API/PortBlog.API.xml | 131 ++++- PortBlog.API/Profiles/ResumeProfile.cs | 10 + PortBlog.API/Program.cs | 42 +- .../Contracts/IResumeRepository.cs | 67 +++ PortBlog.API/Repositories/ResumeRepository.cs | 188 +++++- PortBlog.API/Services/AdminService.cs | 552 ++++++++++++++++++ PortBlog.API/Services/AuthService.cs | 9 +- .../Services/Contracts/IAdminService.cs | 37 ++ PortBlog.Tests/PortBlog.Tests.csproj | 21 + 25 files changed, 1496 insertions(+), 128 deletions(-) create mode 100644 PortBlog.API/Extensions/ConfigureSwaggerOptions.cs create mode 100644 PortBlog.API/Services/AdminService.cs create mode 100644 PortBlog.API/Services/Contracts/IAdminService.cs create mode 100644 PortBlog.Tests/PortBlog.Tests.csproj diff --git a/PortBlog.API.sln b/PortBlog.API.sln index cbbed79..6d7cdb6 100644 --- a/PortBlog.API.sln +++ b/PortBlog.API.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.9.34701.34 +# Visual Studio Version 18 +VisualStudioVersion = 18.1.11304.174 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortBlog.API", "PortBlog.API\PortBlog.API.csproj", "{2E50B5D7-56E2-4E89-8742-BB57FF4245F9}" EndProject @@ -15,32 +15,90 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KBR.Shared", "Shared\KBR.Sh EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KBR.Shared.Lite", "Shared\KBR.Share.Lite\KBR.Shared.Lite.csproj", "{F4B7078B-C59A-46B8-881A-C3CEE2634498}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PortBlog.Tests", "PortBlog.Tests\PortBlog.Tests.csproj", "{11106F82-FC17-497D-8747-CF1A84BFA7F8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Debug|x64.ActiveCfg = Debug|Any CPU + {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Debug|x64.Build.0 = Debug|Any CPU + {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Debug|x86.ActiveCfg = Debug|Any CPU + {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Debug|x86.Build.0 = Debug|Any CPU {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Release|Any CPU.ActiveCfg = Release|Any CPU {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Release|Any CPU.Build.0 = Release|Any CPU + {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Release|x64.ActiveCfg = Release|Any CPU + {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Release|x64.Build.0 = Release|Any CPU + {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Release|x86.ActiveCfg = Release|Any CPU + {2E50B5D7-56E2-4E89-8742-BB57FF4245F9}.Release|x86.Build.0 = Release|Any CPU {26654BFD-EE9B-49BA-84BA-9156AC348076}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {26654BFD-EE9B-49BA-84BA-9156AC348076}.Debug|Any CPU.Build.0 = Debug|Any CPU + {26654BFD-EE9B-49BA-84BA-9156AC348076}.Debug|x64.ActiveCfg = Debug|Any CPU + {26654BFD-EE9B-49BA-84BA-9156AC348076}.Debug|x64.Build.0 = Debug|Any CPU + {26654BFD-EE9B-49BA-84BA-9156AC348076}.Debug|x86.ActiveCfg = Debug|Any CPU + {26654BFD-EE9B-49BA-84BA-9156AC348076}.Debug|x86.Build.0 = Debug|Any CPU {26654BFD-EE9B-49BA-84BA-9156AC348076}.Release|Any CPU.ActiveCfg = Release|Any CPU {26654BFD-EE9B-49BA-84BA-9156AC348076}.Release|Any CPU.Build.0 = Release|Any CPU + {26654BFD-EE9B-49BA-84BA-9156AC348076}.Release|x64.ActiveCfg = Release|Any CPU + {26654BFD-EE9B-49BA-84BA-9156AC348076}.Release|x64.Build.0 = Release|Any CPU + {26654BFD-EE9B-49BA-84BA-9156AC348076}.Release|x86.ActiveCfg = Release|Any CPU + {26654BFD-EE9B-49BA-84BA-9156AC348076}.Release|x86.Build.0 = Release|Any CPU {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Debug|x64.ActiveCfg = Debug|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Debug|x64.Build.0 = Debug|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Debug|x86.ActiveCfg = Debug|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Debug|x86.Build.0 = Debug|Any CPU {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Release|Any CPU.ActiveCfg = Release|Any CPU {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Release|Any CPU.Build.0 = Release|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Release|x64.ActiveCfg = Release|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Release|x64.Build.0 = Release|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Release|x86.ActiveCfg = Release|Any CPU + {DA0B3995-A83A-4D7C-A964-ADFE1F58B1FA}.Release|x86.Build.0 = Release|Any CPU {1C0F86E4-A791-4150-B9B3-B761925681DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1C0F86E4-A791-4150-B9B3-B761925681DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Debug|x64.ActiveCfg = Debug|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Debug|x64.Build.0 = Debug|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Debug|x86.ActiveCfg = Debug|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Debug|x86.Build.0 = Debug|Any CPU {1C0F86E4-A791-4150-B9B3-B761925681DD}.Release|Any CPU.ActiveCfg = Release|Any CPU {1C0F86E4-A791-4150-B9B3-B761925681DD}.Release|Any CPU.Build.0 = Release|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Release|x64.ActiveCfg = Release|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Release|x64.Build.0 = Release|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Release|x86.ActiveCfg = Release|Any CPU + {1C0F86E4-A791-4150-B9B3-B761925681DD}.Release|x86.Build.0 = Release|Any CPU {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Debug|x64.ActiveCfg = Debug|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Debug|x64.Build.0 = Debug|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Debug|x86.ActiveCfg = Debug|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Debug|x86.Build.0 = Debug|Any CPU {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Release|Any CPU.ActiveCfg = Release|Any CPU {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Release|Any CPU.Build.0 = Release|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Release|x64.ActiveCfg = Release|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Release|x64.Build.0 = Release|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Release|x86.ActiveCfg = Release|Any CPU + {F4B7078B-C59A-46B8-881A-C3CEE2634498}.Release|x86.Build.0 = Release|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Debug|x64.ActiveCfg = Debug|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Debug|x64.Build.0 = Debug|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Debug|x86.ActiveCfg = Debug|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Debug|x86.Build.0 = Debug|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Release|Any CPU.Build.0 = Release|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Release|x64.ActiveCfg = Release|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Release|x64.Build.0 = Release|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Release|x86.ActiveCfg = Release|Any CPU + {11106F82-FC17-497D-8747-CF1A84BFA7F8}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PortBlog.API/Controllers/AdminController.cs b/PortBlog.API/Controllers/AdminController.cs index b6cb275..1ef275f 100644 --- a/PortBlog.API/Controllers/AdminController.cs +++ b/PortBlog.API/Controllers/AdminController.cs @@ -1,150 +1,420 @@ using Asp.Versioning; -using AutoMapper; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using PortBlog.API.Models; -using PortBlog.API.Repositories.Contracts; +using PortBlog.API.Services.Contracts; namespace PortBlog.API.Controllers { /// - /// Controller for administrative actions related to candidates and their resumes. + /// Controller for administrative actions related to the logged-in candidate and their resume. + /// All endpoints derive the candidate identity from the access token claims. /// - [Route("api/v{version:apiVersion}/admin")] [ApiController] - [ApiVersion(1)] + [ApiVersion("1.0")] + [Route("api/v{version:apiVersion}/admin")] [Authorize] - public class AdminController(ILogger logger, ICandidateRepository candidateRepository, IResumeRepository resumeRepository, IMapper mapper) : Controller + public class AdminController(ILogger logger, IAdminService adminService) : Controller { /// - /// Get hobbies of the candidate by candidateid + /// Get hobbies of the logged-in candidate. /// - /// The id of the candidate whose hobbies to get - /// Hobbies of the candidate + /// Hobbies and about details of the candidate /// Returns the requested hobbies of the candidate - [HttpGet("GetHobbies/{candidateId}")] - [ProducesResponseType(StatusCodes.Status404NotFound)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] + [HttpGet("GetHobbies")] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetHobbies(int candidateId) + public async Task> GetHobbies() { try { - if (!await candidateRepository.CandidateExistAsync(candidateId)) - { - logger.LogInformation("Candidate with id {CandidateId} wasn't found when fetching about details.", candidateId); - return NotFound(); - } - - var aboutDetails = await resumeRepository.GetHobbiesAsync(candidateId); - - return Ok(mapper.Map(aboutDetails)); - + var candidateId = adminService.GetCandidateIdFromClaims(User); + var aboutDetails = await adminService.GetHobbiesAsync(candidateId); + return Ok(aboutDetails); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when fetching hobbies."); + return Unauthorized(ex.Message); } catch (Exception ex) { - logger.LogCritical(ex, "Exception while getting about details for the candidate with id {CandidateId}.", candidateId); + logger.LogCritical(ex, "Exception while getting about details."); return StatusCode(500, "A problem happened while handling your request."); } } /// - /// Get Candidate details with social links by candidateid + /// Get contact details (candidate with social links) for the logged-in candidate. /// - /// The id of the candidate whose detials to get with social links - /// Candidate details with sociallinks + /// Candidate details with social links /// Returns the requested candidate details with social links - [HttpGet("GetCandidateWithSocialLinks/{candidateId}")] - [ProducesResponseType(StatusCodes.Status404NotFound)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] + [HttpGet("GetCandidateWithSocialLinks")] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetContact(int candidateId) + public async Task> GetContact() { try { - if (!await candidateRepository.CandidateExistAsync(candidateId)) - { - logger.LogInformation("Candidate with id {CandidateId} wasn't found when fetching candidate with social links.", candidateId); - return NotFound(); - } - - var contact = await resumeRepository.GetCandidateWithSocialLinksAsync(candidateId); - - return Ok(mapper.Map(contact)); - + var candidateId = adminService.GetCandidateIdFromClaims(User); + var contact = await adminService.GetContactAsync(candidateId); + return Ok(contact); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when fetching contact."); + return Unauthorized(ex.Message); } catch (Exception ex) { - logger.LogCritical(ex, "Exception while getting contact for the candidate with social links with id {CandidateId}.", candidateId); + logger.LogCritical(ex, "Exception while getting contact details."); return StatusCode(500, "A problem happened while handling your request."); } } /// - /// Get Candidate resume by candidateid + /// Get resume for the logged-in candidate. /// - /// The id of the candidate whose resume to get /// Candidate resume /// Returns the requested candidate resume - [HttpGet("GetResume/{candidateId}")] - [ProducesResponseType(StatusCodes.Status404NotFound)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] + [HttpGet("GetResume")] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetResume(int candidateId) + public async Task> GetResume() { try { - if (!await candidateRepository.CandidateExistAsync(candidateId)) - { - logger.LogInformation("Candidate with id {CandidateId} wasn't found when fetching resume.", candidateId); - return NotFound(); - } - - var resume = await resumeRepository.GetResumeAsync(candidateId); - - return Ok(mapper.Map(resume)); - + var candidateId = adminService.GetCandidateIdFromClaims(User); + var resume = await adminService.GetResumeAsync(candidateId); + return Ok(resume); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when fetching resume."); + return Unauthorized(ex.Message); } catch (Exception ex) { - logger.LogCritical(ex, "Exception while getting resume for the candidate with id {CandidateId}.", candidateId); + logger.LogCritical(ex, "Exception while getting resume."); return StatusCode(500, "A problem happened while handling your request."); } } /// - /// Get Candidate projects by candidateid + /// Get projects for the logged-in candidate. /// - /// The id of the candidate whose projects to get /// Candidate projects /// Returns the requested candidate projects - [HttpGet("GetProjects/{candidateId}")] - [ProducesResponseType(StatusCodes.Status404NotFound)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] + [HttpGet("GetProjects")] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetProjects(int candidateId) + public async Task> GetProjects() { try { - if (!await candidateRepository.CandidateExistAsync(candidateId)) - { - logger.LogInformation("Candidate with id {CandidateId} wasn't found when fetching projects.", candidateId); - return NotFound(); - } - - var projects = await resumeRepository.GetProjectsAsync(candidateId); - - return Ok(mapper.Map(projects)); - + var candidateId = adminService.GetCandidateIdFromClaims(User); + var projects = await adminService.GetProjectsAsync(candidateId); + return Ok(projects); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when fetching projects."); + return Unauthorized(ex.Message); } catch (Exception ex) { - logger.LogCritical(ex, "Exception while getting projects for the candidate with id {CandidateId}.", candidateId); + logger.LogCritical(ex, "Exception while getting projects."); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Create or update a project for the logged-in candidate's resume. + /// + [HttpPost("UpsertProject")] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> UpsertProject([FromBody] ProjectDto projectDto) + { + try + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var candidateId = adminService.GetCandidateIdFromClaims(User); + var result = await adminService.UpsertProjectAsync(candidateId, projectDto); + return Ok(result); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when upserting project."); + return Unauthorized(ex.Message); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Exception while upserting project."); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Delete a project from the logged-in candidate's resume. + /// + /// The id of the project to delete + [HttpDelete("DeleteProject/{projectId}")] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task DeleteProject(int projectId) + { + try + { + var candidateId = adminService.GetCandidateIdFromClaims(User); + var deleted = await adminService.DeleteProjectAsync(candidateId, projectId); + if (!deleted) + { + return NotFound(); + } + return Ok(); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when deleting project."); + return Unauthorized(ex.Message); + } + catch (KeyNotFoundException ex) + { + logger.LogInformation(ex, "Resume not found when deleting project."); + return NotFound(); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Exception while deleting project {ProjectId}.", projectId); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Create, update, or remove hobbies and update the about section for the logged-in candidate. + /// Hobbies present in the list are added or updated; hobbies not in the list are removed. + /// + [HttpPost("UpsertHobbies")] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> UpsertHobbies([FromBody] AboutDto aboutDto) + { + try + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var candidateId = adminService.GetCandidateIdFromClaims(User); + var result = await adminService.UpsertHobbiesAsync(candidateId, aboutDto); + return Ok(result); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when upserting hobbies."); + return Unauthorized(ex.Message); + } + catch (KeyNotFoundException ex) + { + logger.LogInformation(ex, "Resume not found when upserting hobbies."); + return NotFound(); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Exception while upserting hobbies."); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Create, update, or remove skills for the logged-in candidate's resume. + /// Skills present in the list are added or updated; skills not in the list are removed. + /// + [HttpPost("UpsertSkills")] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> UpsertSkills([FromBody] IEnumerable skillDtos) + { + try + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var candidateId = adminService.GetCandidateIdFromClaims(User); + var result = await adminService.UpsertSkillsAsync(candidateId, skillDtos); + return Ok(result); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when upserting skills."); + return Unauthorized(ex.Message); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Exception while upserting skills."); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Create, update, or remove academics for the logged-in candidate's resume. + /// Academics present in the list are added or updated; academics not in the list are removed. + /// + [HttpPost("UpsertAcademics")] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> UpsertAcademics([FromBody] IEnumerable academicDtos) + { + try + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var candidateId = adminService.GetCandidateIdFromClaims(User); + var result = await adminService.UpsertAcademicsAsync(candidateId, academicDtos); + return Ok(result); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when upserting academics."); + return Unauthorized(ex.Message); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Exception while upserting academics."); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Create, update, or remove experiences for the logged-in candidate's resume. + /// Experiences present in the list are added or updated; experiences not in the list are removed. + /// + [HttpPost("UpsertExperiences")] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> UpsertExperiences([FromBody] IEnumerable experienceDtos) + { + try + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var candidateId = adminService.GetCandidateIdFromClaims(User); + var result = await adminService.UpsertExperiencesAsync(candidateId, experienceDtos); + return Ok(result); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when upserting experiences."); + return Unauthorized(ex.Message); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Exception while upserting experiences."); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Create, update, or remove certifications for the logged-in candidate's resume. + /// Certifications present in the list are added or updated; certifications not in the list are removed. + /// + [HttpPost("UpsertCertifications")] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> UpsertCertifications([FromBody] IEnumerable certificationDtos) + { + try + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var candidateId = adminService.GetCandidateIdFromClaims(User); + var result = await adminService.UpsertCertificationsAsync(candidateId, certificationDtos); + return Ok(result); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when upserting certifications."); + return Unauthorized(ex.Message); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Exception while upserting certifications."); + return StatusCode(500, "A problem happened while handling your request."); + } + } + + /// + /// Create or update contact information (candidate with social links) for the logged-in candidate. + /// + [HttpPost("UpsertContact")] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> UpsertContact([FromBody] CandidateSocialLinksDto contactDto) + { + try + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var candidateId = adminService.GetCandidateIdFromClaims(User); + var result = await adminService.UpsertContactAsync(candidateId, contactDto); + return Ok(result); + } + catch (UnauthorizedAccessException ex) + { + logger.LogInformation(ex, "Unauthorized access when upserting contact."); + return Unauthorized(ex.Message); + } + catch (KeyNotFoundException ex) + { + logger.LogInformation(ex, "Resume not found when upserting contact."); + return NotFound(); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Exception while upserting contact."); return StatusCode(500, "A problem happened while handling your request."); } } diff --git a/PortBlog.API/Controllers/AuthController.cs b/PortBlog.API/Controllers/AuthController.cs index d1bf7dd..4b599f6 100644 --- a/PortBlog.API/Controllers/AuthController.cs +++ b/PortBlog.API/Controllers/AuthController.cs @@ -12,9 +12,9 @@ namespace PortBlog.API.Controllers /// /// Controller for handling authentication-related operations. /// - [Route("api/v{version:apiVersion}/auth")] [ApiController] - [ApiVersion(1)] + [ApiVersion("1.0")] + [Route("api/v{version:apiVersion}/auth")] public class AuthController(IAuthService authService, IMailService mailService, ICandidateRepository candidateRepository, ILogger logger, IMapper mapper, IConfiguration configuration, ITemplateService templateService, IAppDistributedCache cache) : ControllerBase { /// diff --git a/PortBlog.API/Controllers/BlogController.cs b/PortBlog.API/Controllers/BlogController.cs index ecc4ef5..b8319ef 100644 --- a/PortBlog.API/Controllers/BlogController.cs +++ b/PortBlog.API/Controllers/BlogController.cs @@ -10,7 +10,7 @@ namespace PortBlog.API.Controllers { [Route("blog/api/v{version:apiVersion}/posts")] [ApiController] - [ApiVersion(1)] + [ApiVersion("1.0")] public class BlogController : ControllerBase { private readonly ILogger _logger; diff --git a/PortBlog.API/Controllers/CvController.cs b/PortBlog.API/Controllers/CvController.cs index da59e1d..f39e309 100644 --- a/PortBlog.API/Controllers/CvController.cs +++ b/PortBlog.API/Controllers/CvController.cs @@ -7,9 +7,9 @@ using PortBlog.API.Services.Contracts; namespace PortBlog.API.Controllers { - [Route("api/v{versions:apiVersion}/cv")] [ApiController] - [ApiVersion(1)] + [ApiVersion("1.0")] + [Route("api/v{version:apiVersion}/cv")] public class CvController : ControllerBase { private readonly ILogger _logger; @@ -37,7 +37,7 @@ namespace PortBlog.API.Controllers /// Returns the requested cv of the candidate [HttpGet("{candidateId}")] [Obsolete] - [ApiVersion(0.1, Deprecated = true)] + [ApiVersion("0.1", Deprecated = true)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] diff --git a/PortBlog.API/Controllers/PostController.cs b/PortBlog.API/Controllers/PostController.cs index bce5fd9..dda284b 100644 --- a/PortBlog.API/Controllers/PostController.cs +++ b/PortBlog.API/Controllers/PostController.cs @@ -1,9 +1,11 @@ -using Microsoft.AspNetCore.Mvc; +using Asp.Versioning; +using Microsoft.AspNetCore.Mvc; namespace PortBlog.API.Controllers { - [Route("api/blog/post")] + [ApiVersionNeutral] [ApiController] + [Route("api/v{version:apiVersion}/blog/post")] public class PostController : ControllerBase { private readonly ILogger _logger; diff --git a/PortBlog.API/Extensions/ConfigureSwaggerOptions.cs b/PortBlog.API/Extensions/ConfigureSwaggerOptions.cs new file mode 100644 index 0000000..6e6a928 --- /dev/null +++ b/PortBlog.API/Extensions/ConfigureSwaggerOptions.cs @@ -0,0 +1,28 @@ +using Asp.Versioning.ApiExplorer; +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +public class ConfigureSwaggerOptions : IConfigureOptions +{ + private readonly IApiVersionDescriptionProvider _provider; + + public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) + { + _provider = provider; + } + + public void Configure(SwaggerGenOptions options) + { + foreach (var description in _provider.ApiVersionDescriptions) + { + options.SwaggerDoc( + description.GroupName, + new OpenApiInfo + { + Title = "PortBlog API", + Version = description.GroupName + }); + } + } +} diff --git a/PortBlog.API/Extensions/ServiceExtensions.cs b/PortBlog.API/Extensions/ServiceExtensions.cs index 39b1282..4c98ba0 100644 --- a/PortBlog.API/Extensions/ServiceExtensions.cs +++ b/PortBlog.API/Extensions/ServiceExtensions.cs @@ -21,6 +21,7 @@ namespace PortBlog.API.Extensions services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddScoped(); return services; } } diff --git a/PortBlog.API/Models/AcademicDto.cs b/PortBlog.API/Models/AcademicDto.cs index f2386fd..893fd0f 100644 --- a/PortBlog.API/Models/AcademicDto.cs +++ b/PortBlog.API/Models/AcademicDto.cs @@ -2,7 +2,7 @@ { public class AcademicDto { - public int AcademicId { get; set; } + public int? AcademicId { get; set; } public string Institution { get; set; } = string.Empty; diff --git a/PortBlog.API/Models/CertificationDto.cs b/PortBlog.API/Models/CertificationDto.cs index 8447ca0..650f68c 100644 --- a/PortBlog.API/Models/CertificationDto.cs +++ b/PortBlog.API/Models/CertificationDto.cs @@ -2,7 +2,7 @@ { public class CertificationDto { - public int CertificationId { get; set; } + public int? CertificationId { get; set; } public string CertificationName { get; set; } = string.Empty; diff --git a/PortBlog.API/Models/ExperienceDetailsDto.cs b/PortBlog.API/Models/ExperienceDetailsDto.cs index 034a67d..ec82888 100644 --- a/PortBlog.API/Models/ExperienceDetailsDto.cs +++ b/PortBlog.API/Models/ExperienceDetailsDto.cs @@ -2,7 +2,7 @@ { public class ExperienceDetailsDto { - public int Id { get; set; } + public int? Id { get; set; } public string Details { get; set; } = string.Empty; diff --git a/PortBlog.API/Models/ExperienceDto.cs b/PortBlog.API/Models/ExperienceDto.cs index cb9dc9f..ad6fe8e 100644 --- a/PortBlog.API/Models/ExperienceDto.cs +++ b/PortBlog.API/Models/ExperienceDto.cs @@ -4,7 +4,7 @@ namespace PortBlog.API.Models { public class ExperienceDto { - public int ExperienceId { get; set; } + public int? ExperienceId { get; set; } public string Title { get; set; } = string.Empty; @@ -12,10 +12,31 @@ namespace PortBlog.API.Models public string Company { get; set; } = string.Empty; + public string? Location { get; set; } + + /// + /// Full start date for write operations (e.g. "2020-01-01"). + /// + public DateTime? StartDate { get; set; } + + /// + /// Full end date for write operations. Null means "Present". + /// + public DateTime? EndDate { get; set; } + + /// + /// Read-only display value: start year (e.g. "2020"). Mapped from entity on read. + /// public string StartYear { get; set; } = string.Empty; + /// + /// Read-only display value: end year (e.g. "2023" or "Present"). Mapped from entity on read. + /// public string EndYear { get; set; } = string.Empty; + /// + /// Read-only display value: formatted period (e.g. "Jan 2020 - Mar 2023"). Mapped from entity on read. + /// public string Period { get; set; } = string.Empty; public ICollection Details { get; set; } = new List(); diff --git a/PortBlog.API/Models/HobbyDto.cs b/PortBlog.API/Models/HobbyDto.cs index 22d91ea..4116eb6 100644 --- a/PortBlog.API/Models/HobbyDto.cs +++ b/PortBlog.API/Models/HobbyDto.cs @@ -2,7 +2,7 @@ { public class HobbyDto { - public int HobbyId { get; set; } + public int? HobbyId { get; set; } public string Name { get; set; } = string.Empty; diff --git a/PortBlog.API/Models/ProjectDto.cs b/PortBlog.API/Models/ProjectDto.cs index be20506..8de39a2 100644 --- a/PortBlog.API/Models/ProjectDto.cs +++ b/PortBlog.API/Models/ProjectDto.cs @@ -4,7 +4,7 @@ namespace PortBlog.API.Models { public class ProjectDto { - public int ProjectId { get; set; } + public int? ProjectId { get; set; } public string Name { get; set; } = string.Empty; diff --git a/PortBlog.API/Models/SkillDto.cs b/PortBlog.API/Models/SkillDto.cs index eb5581a..c83d3e3 100644 --- a/PortBlog.API/Models/SkillDto.cs +++ b/PortBlog.API/Models/SkillDto.cs @@ -2,7 +2,7 @@ { public class SkillDto { - public int SkillId { get; set; } + public int? SkillId { get; set; } public string Name { get; set; } = string.Empty; diff --git a/PortBlog.API/PortBlog.API.csproj b/PortBlog.API/PortBlog.API.csproj index 303fa5a..aabb708 100644 --- a/PortBlog.API/PortBlog.API.csproj +++ b/PortBlog.API/PortBlog.API.csproj @@ -9,6 +9,7 @@ + diff --git a/PortBlog.API/PortBlog.API.xml b/PortBlog.API/PortBlog.API.xml index 274a32b..9fd26c2 100644 --- a/PortBlog.API/PortBlog.API.xml +++ b/PortBlog.API/PortBlog.API.xml @@ -6,46 +6,90 @@ - Controller for administrative actions related to candidates and their resumes. + Controller for administrative actions related to the logged-in candidate and their resume. + All endpoints derive the candidate identity from the access token claims. - + - Controller for administrative actions related to candidates and their resumes. + Controller for administrative actions related to the logged-in candidate and their resume. + All endpoints derive the candidate identity from the access token claims. - + - Get hobbies of the candidate by candidateid + Get hobbies of the logged-in candidate. - The id of the candidate whose hobbies to get - Hobbies of the candidate + Hobbies and about details of the candidate Returns the requested hobbies of the candidate - + - Get Candidate details with social links by candidateid + Get contact details (candidate with social links) for the logged-in candidate. - The id of the candidate whose detials to get with social links - Candidate details with sociallinks + Candidate details with social links Returns the requested candidate details with social links - + - Get Candidate resume by candidateid + Get resume for the logged-in candidate. - The id of the candidate whose resume to get Candidate resume Returns the requested candidate resume - + - Get Candidate projects by candidateid + Get projects for the logged-in candidate. - The id of the candidate whose projects to get Candidate projects Returns the requested candidate projects + + + Create or update a project for the logged-in candidate's resume. + + + + + Delete a project from the logged-in candidate's resume. + + The id of the project to delete + + + + Create, update, or remove hobbies and update the about section for the logged-in candidate. + Hobbies present in the list are added or updated; hobbies not in the list are removed. + + + + + Create, update, or remove skills for the logged-in candidate's resume. + Skills present in the list are added or updated; skills not in the list are removed. + + + + + Create, update, or remove academics for the logged-in candidate's resume. + Academics present in the list are added or updated; academics not in the list are removed. + + + + + Create, update, or remove experiences for the logged-in candidate's resume. + Experiences present in the list are added or updated; experiences not in the list are removed. + + + + + Create, update, or remove certifications for the logged-in candidate's resume. + Certifications present in the list are added or updated; certifications not in the list are removed. + + + + + Create or update contact information (candidate with social links) for the logged-in candidate. + + Controller for handling authentication-related operations. @@ -401,6 +445,31 @@ The project categories of all the projects + + + Full start date for write operations (e.g. "2020-01-01"). + + + + + Full end date for write operations. Null means "Present". + + + + + Read-only display value: start year (e.g. "2020"). Mapped from entity on read. + + + + + Read-only display value: end year (e.g. "2023" or "Present"). Mapped from entity on read. + + + + + Read-only display value: formatted period (e.g. "Jan 2020 - Mar 2023"). Mapped from entity on read. + + CV details of the candidate @@ -421,6 +490,29 @@ The work experiences of the candidate + + + Repository for managing resume-related data access and operations. + + + + + Retrieves the latest resume for a candidate, optionally including related data. + + The ID of the candidate. + If true, includes related data such as academics, experiences, social links, etc. + The latest for the candidate, or null if not found. + + + + Service for administrative operations related to candidates, resumes, and their associated data. + + + + + Service for administrative operations related to candidates, resumes, and their associated data. + + Provides authentication services such as OTP generation, validation, and JWT token management. @@ -493,6 +585,11 @@ The refresh token to revoke. A task that represents the asynchronous revoke operation. + + + Service for administrative operations related to candidates, resumes, and their associated data. + + Provides authentication-related services such as OTP generation, token management, and refresh token handling. diff --git a/PortBlog.API/Profiles/ResumeProfile.cs b/PortBlog.API/Profiles/ResumeProfile.cs index a3ebc8d..975e1b2 100644 --- a/PortBlog.API/Profiles/ResumeProfile.cs +++ b/PortBlog.API/Profiles/ResumeProfile.cs @@ -35,6 +35,16 @@ namespace PortBlog.API.Profiles ( dest => dest.EndYear, opts => opts.MapFrom(src => src.EndDate != null ? src.EndDate.Value.Year.ToString() : "Present") + ) + .ForMember + ( + dest => dest.StartDate, + opts => opts.MapFrom(src => src.StartDate) + ) + .ForMember + ( + dest => dest.EndDate, + opts => opts.MapFrom(src => src.EndDate) ); CreateMap(); CreateMap() diff --git a/PortBlog.API/Program.cs b/PortBlog.API/Program.cs index 9d9e7d0..1389589 100644 --- a/PortBlog.API/Program.cs +++ b/PortBlog.API/Program.cs @@ -99,17 +99,19 @@ builder.Services.AddAutoMapper(cfg => cfg.AddMaps(AppDomain.CurrentDomain.GetAss builder.Services.AddCache(builder.Configuration); -// Registering API Versioning Specification services -builder.Services.AddApiVersioning(setupAction => -{ - setupAction.ReportApiVersions = true; - setupAction.AssumeDefaultVersionWhenUnspecified = true; - setupAction.DefaultApiVersion = new ApiVersion(1, 0); -}).AddMvc() -.AddApiExplorer(setupAction => -{ - setupAction.SubstituteApiVersionInUrl = true; -}); +builder.Services + .AddApiVersioning(options => + { + options.DefaultApiVersion = new ApiVersion(1, 0); + options.AssumeDefaultVersionWhenUnspecified = true; + options.ReportApiVersions = true; + }) + .AddMvc() // IMPORTANT + .AddApiExplorer(options => + { + options.GroupNameFormat = "'v'V"; + options.SubstituteApiVersionInUrl = true; + }); builder.Services.AddSwaggerGen(c => { @@ -168,6 +170,8 @@ builder.Services.AddSwaggerGen(c => c.AddSecurityRequirement(requirement); }); +builder.Services.ConfigureOptions(); + var jwtKey = builder.Configuration["Jwt:Key"]; if (string.IsNullOrEmpty(jwtKey)) { @@ -196,8 +200,6 @@ builder.Services.AddAuthentication(options => var app = builder.Build(); -app.UseCors(); - if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler(); @@ -211,6 +213,12 @@ if (app.Environment.IsDevelopment()) { // Get the IApiVersionDescriptionProvider from the app's service provider var apiVersionDescriptionProvider = app.Services.GetRequiredService(); + + foreach (var d in apiVersionDescriptionProvider.ApiVersionDescriptions) + { + Console.WriteLine($"GroupName: {d.GroupName}"); + } + foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions) { setupAction.SwaggerEndpoint( @@ -229,12 +237,16 @@ app.UseStaticFiles(new StaticFileOptions() RequestPath = new PathString("/images") }); +app.UseRouting(); + +app.UseCors(); + +app.UseMiddleware(); + app.UseAuthentication(); app.UseAuthorization(); -app.UseMiddleware(); - app.MapControllers(); app.Run(); diff --git a/PortBlog.API/Repositories/Contracts/IResumeRepository.cs b/PortBlog.API/Repositories/Contracts/IResumeRepository.cs index c221769..9bd11d0 100644 --- a/PortBlog.API/Repositories/Contracts/IResumeRepository.cs +++ b/PortBlog.API/Repositories/Contracts/IResumeRepository.cs @@ -15,5 +15,72 @@ namespace PortBlog.API.Repositories.Contracts Task GetProjectsAsync(int candidateId); Task GetBlogAsync(int candidate); + + // Added for admin write operations used by controllers + Task GetByIdAsync(int resumeId); + + Task GetByIdWithCollectionsAsync(int resumeId); + + Task GetProjectAsync(int projectId); + + Task GetHobbyAsync(int hobbyId); + + Task> GetHobbiesByResumeIdAsync(int resumeId); + + Task GetCandidateByIdAsync(int candidateId); + + void AddProject(Project project); + + void UpdateProject(Project project); + + void RemoveProject(Project project); + + void AddHobby(Hobby hobby); + + void UpdateHobby(Hobby hobby); + + void RemoveHobby(Hobby hobby); + + void AddSkill(Skill skill); + + void UpdateSkill(Skill skill); + + void RemoveSkill(Skill skill); + + void AddAcademic(Academic academic); + + void UpdateAcademic(Academic academic); + + void RemoveAcademic(Academic academic); + + void AddExperience(Experience experience); + + void UpdateExperience(Experience experience); + + void RemoveExperience(Experience experience); + + void AddExperienceDetails(ExperienceDetails details); + + void UpdateExperienceDetails(ExperienceDetails details); + + void RemoveExperienceDetails(ExperienceDetails details); + + void AddCertification(Certification certification); + + void UpdateCertification(Certification certification); + + void RemoveCertification(Certification certification); + + void AddResume(Resume resume); + + void UpdateResume(Resume resume); + + void UpdateCandidate(Candidate candidate); + + void AddSocialLink(SocialLinks socialLink); + + void UpdateSocialLink(SocialLinks socialLink); + + Task SaveChangesAsync(); } } diff --git a/PortBlog.API/Repositories/ResumeRepository.cs b/PortBlog.API/Repositories/ResumeRepository.cs index 534ba9b..ea4368f 100644 --- a/PortBlog.API/Repositories/ResumeRepository.cs +++ b/PortBlog.API/Repositories/ResumeRepository.cs @@ -1,11 +1,13 @@ using Microsoft.EntityFrameworkCore; using PortBlog.API.DbContexts; using PortBlog.API.Entities; -using PortBlog.API.Models; using PortBlog.API.Repositories.Contracts; namespace PortBlog.API.Repositories { + /// + /// Repository for managing resume-related data access and operations. + /// public class ResumeRepository : IResumeRepository { private readonly CvBlogContext _cvBlogContext; @@ -14,9 +16,16 @@ namespace PortBlog.API.Repositories { _cvBlogContext = cvBlogContext; } + + /// + /// Retrieves the latest resume for a candidate, optionally including related data. + /// + /// The ID of the candidate. + /// If true, includes related data such as academics, experiences, social links, etc. + /// The latest for the candidate, or null if not found. public async Task GetLatestResumeForCandidateAsync(int candidateId, bool includeOtherData) { - if(includeOtherData) + if (includeOtherData) { return await _cvBlogContext.Resumes .Include(r => r.Candidate) @@ -83,5 +92,180 @@ namespace PortBlog.API.Repositories return result?.SocialLinks?.Blog; } + + // New read helpers + public async Task GetByIdAsync(int resumeId) + { + return await _cvBlogContext.Resumes.FirstOrDefaultAsync(r => r.ResumeId == resumeId); + } + + public async Task GetByIdWithCollectionsAsync(int resumeId) + { + return await _cvBlogContext.Resumes + .Include(r => r.Skills) + .Include(r => r.Academics) + .Include(r => r.Experiences) + .ThenInclude(e => e.Details) + .Include(r => r.Certifications) + .Include(r => r.Projects) + .FirstOrDefaultAsync(r => r.ResumeId == resumeId); + } + + public async Task GetProjectAsync(int projectId) + { + return await _cvBlogContext.Projects.FirstOrDefaultAsync(p => p.ProjectId == projectId); + } + + public async Task GetHobbyAsync(int hobbyId) + { + return await _cvBlogContext.Hobbies.FirstOrDefaultAsync(h => h.HobbyId == hobbyId); + } + + public async Task> GetHobbiesByResumeIdAsync(int resumeId) + { + return await _cvBlogContext.Hobbies.Where(h => h.ResumeId == resumeId).ToListAsync(); + } + + public async Task GetCandidateByIdAsync(int candidateId) + { + return await _cvBlogContext.Candidates + .FirstOrDefaultAsync(c => c.CandidateId == candidateId); + } + + // New write helpers + public void AddProject(Project project) + { + _cvBlogContext.Projects.Add(project); + } + + public void UpdateProject(Project project) + { + _cvBlogContext.Projects.Update(project); + } + + public void RemoveProject(Project project) + { + _cvBlogContext.Projects.Remove(project); + } + + public void AddHobby(Hobby hobby) + { + _cvBlogContext.Hobbies.Add(hobby); + } + + public void UpdateHobby(Hobby hobby) + { + _cvBlogContext.Hobbies.Update(hobby); + } + + public void RemoveHobby(Hobby hobby) + { + _cvBlogContext.Hobbies.Remove(hobby); + } + + public void AddSkill(Skill skill) + { + _cvBlogContext.Skills.Add(skill); + } + + public void UpdateSkill(Skill skill) + { + _cvBlogContext.Skills.Update(skill); + } + + public void RemoveSkill(Skill skill) + { + _cvBlogContext.Skills.Remove(skill); + } + + public void AddAcademic(Academic academic) + { + _cvBlogContext.Academics.Add(academic); + } + + public void UpdateAcademic(Academic academic) + { + _cvBlogContext.Academics.Update(academic); + } + + public void RemoveAcademic(Academic academic) + { + _cvBlogContext.Academics.Remove(academic); + } + + public void AddExperience(Experience experience) + { + _cvBlogContext.Experiences.Add(experience); + } + + public void UpdateExperience(Experience experience) + { + _cvBlogContext.Experiences.Update(experience); + } + + public void RemoveExperience(Experience experience) + { + _cvBlogContext.Experiences.Remove(experience); + } + + public void AddExperienceDetails(ExperienceDetails details) + { + _cvBlogContext.ExperienceDetails.Add(details); + } + + public void UpdateExperienceDetails(ExperienceDetails details) + { + _cvBlogContext.ExperienceDetails.Update(details); + } + + public void RemoveExperienceDetails(ExperienceDetails details) + { + _cvBlogContext.ExperienceDetails.Remove(details); + } + + public void AddCertification(Certification certification) + { + _cvBlogContext.Certifications.Add(certification); + } + + public void UpdateCertification(Certification certification) + { + _cvBlogContext.Certifications.Update(certification); + } + + public void RemoveCertification(Certification certification) + { + _cvBlogContext.Certifications.Remove(certification); + } + + public void AddResume(Resume resume) + { + _cvBlogContext.Resumes.Add(resume); + } + + public void UpdateResume(Resume resume) + { + _cvBlogContext.Resumes.Update(resume); + } + + public void UpdateCandidate(Candidate candidate) + { + _cvBlogContext.Candidates.Update(candidate); + } + + public void AddSocialLink(SocialLinks socialLink) + { + _cvBlogContext.SocialLinks.Add(socialLink); + } + + public void UpdateSocialLink(SocialLinks socialLink) + { + _cvBlogContext.SocialLinks.Update(socialLink); + } + + public async Task SaveChangesAsync() + { + return (await _cvBlogContext.SaveChangesAsync() >= 0); + } } } diff --git a/PortBlog.API/Services/AdminService.cs b/PortBlog.API/Services/AdminService.cs new file mode 100644 index 0000000..3add174 --- /dev/null +++ b/PortBlog.API/Services/AdminService.cs @@ -0,0 +1,552 @@ +using System.Security.Claims; +using AutoMapper; +using PortBlog.API.Entities; +using PortBlog.API.Models; +using PortBlog.API.Repositories.Contracts; +using PortBlog.API.Services.Contracts; + +namespace PortBlog.API.Services +{ + /// + /// Service for administrative operations related to candidates, resumes, and their associated data. + /// + public class AdminService(ICandidateRepository candidateRepository, IResumeRepository resumeRepository, IMapper mapper) : IAdminService + { + public int GetCandidateIdFromClaims(ClaimsPrincipal user) + { + var candidateIdClaim = user.FindFirst("CandidateId")?.Value; + if (string.IsNullOrEmpty(candidateIdClaim) || !int.TryParse(candidateIdClaim, out var candidateId)) + { + throw new UnauthorizedAccessException("CandidateId claim is missing or invalid."); + } + return candidateId; + } + + public async Task GetHobbiesAsync(int candidateId) + { + var aboutDetails = await resumeRepository.GetHobbiesAsync(candidateId); + return aboutDetails != null ? mapper.Map(aboutDetails) : null; + } + + public async Task GetContactAsync(int candidateId) + { + var contact = await resumeRepository.GetCandidateWithSocialLinksAsync(candidateId); + return contact != null ? mapper.Map(contact) : null; + } + + public async Task GetResumeAsync(int candidateId) + { + var resume = await resumeRepository.GetResumeAsync(candidateId); + return resume != null ? mapper.Map(resume) : null; + } + + public async Task GetProjectsAsync(int candidateId) + { + var projects = await resumeRepository.GetProjectsAsync(candidateId); + return projects != null ? mapper.Map(projects) : null; + } + + public async Task UpsertProjectAsync(int candidateId, ProjectDto projectDto) + { + var resumeWithCollections = await GetOrCreateResumeWithCollectionsAsync(candidateId); + + Project? projectEntity = null; + if (projectDto.ProjectId > 0) + { + projectEntity = await resumeRepository.GetProjectAsync(projectDto.ProjectId.Value); + } + + if (projectEntity == null) + { + projectEntity = new Project + { + Name = projectDto.Name, + Description = projectDto.Description, + Categories = projectDto.Categories ?? Array.Empty(), + Roles = projectDto.Roles != null ? string.Join(",", projectDto.Roles) : null, + Responsibilities = projectDto.Responsibilities != null ? string.Join(",", projectDto.Responsibilities) : null, + TechnologiesUsed = projectDto.TechnologiesUsed != null ? string.Join(",", projectDto.TechnologiesUsed) : null, + Challenges = projectDto.Challenges, + LessonsLearned = projectDto.LessonsLearned, + Impact = projectDto.Impact, + StartDate = projectDto.StartDate == default ? null : projectDto.StartDate, + EndDate = projectDto.EndDate == default ? null : projectDto.EndDate, + ImagePath = projectDto.ImagePath, + Status = projectDto.Status, + ResumeId = resumeWithCollections.ResumeId + }; + + resumeRepository.AddProject(projectEntity); + } + else + { + projectEntity.Name = projectDto.Name; + projectEntity.Description = projectDto.Description; + projectEntity.Categories = projectDto.Categories ?? Array.Empty(); + projectEntity.Roles = projectDto.Roles != null ? string.Join(",", projectDto.Roles) : projectEntity.Roles; + projectEntity.Responsibilities = projectDto.Responsibilities != null ? string.Join(",", projectDto.Responsibilities) : projectEntity.Responsibilities; + projectEntity.TechnologiesUsed = projectDto.TechnologiesUsed != null ? string.Join(",", projectDto.TechnologiesUsed) : projectEntity.TechnologiesUsed; + projectEntity.Challenges = projectDto.Challenges; + projectEntity.LessonsLearned = projectDto.LessonsLearned; + projectEntity.Impact = projectDto.Impact; + projectEntity.StartDate = projectDto.StartDate == default ? projectEntity.StartDate : projectDto.StartDate; + projectEntity.EndDate = projectDto.EndDate == default ? projectEntity.EndDate : projectDto.EndDate; + projectEntity.ImagePath = projectDto.ImagePath; + projectEntity.Status = projectDto.Status; + + resumeRepository.UpdateProject(projectEntity); + } + + await resumeRepository.SaveChangesAsync(); + + return mapper.Map(projectEntity); + } + + public async Task DeleteProjectAsync(int candidateId, int projectId) + { + var resume = await resumeRepository.GetLatestResumeForCandidateAsync(candidateId, includeOtherData: false) + ?? throw new KeyNotFoundException($"Resume for candidate {candidateId} not found."); + + var project = await resumeRepository.GetProjectAsync(projectId); + if (project == null || project.ResumeId != resume.ResumeId) + { + return false; + } + + resumeRepository.RemoveProject(project); + await resumeRepository.SaveChangesAsync(); + return true; + } + + public async Task UpsertHobbiesAsync(int candidateId, AboutDto aboutDto) + { + var resume = await resumeRepository.GetLatestResumeForCandidateAsync(candidateId, includeOtherData: false) + ?? throw new KeyNotFoundException($"Resume for candidate {candidateId} not found."); + + // Update About + if (!string.IsNullOrWhiteSpace(aboutDto.About)) + { + resume.About = aboutDto.About; + resumeRepository.UpdateResume(resume); + } + + // Upsert Hobbies + var existingHobbies = (await resumeRepository.GetHobbiesByResumeIdAsync(resume.ResumeId)).ToList(); + var incomingIds = aboutDto.Hobbies.Where(h => h.HobbyId > 0).Select(h => h.HobbyId).ToHashSet(); + + foreach (var existing in existingHobbies) + { + if (!incomingIds.Contains(existing.HobbyId)) + { + resumeRepository.RemoveHobby(existing); + } + } + + var order = 1; + var resultEntities = new List(); + + foreach (var hobbyDto in aboutDto.Hobbies) + { + Hobby? hobbyEntity = null; + + if (hobbyDto.HobbyId > 0) + { + hobbyEntity = existingHobbies.FirstOrDefault(h => h.HobbyId == hobbyDto.HobbyId); + } + + if (hobbyEntity == null) + { + hobbyEntity = new Hobby + { + Name = hobbyDto.Name, + Description = hobbyDto.Description, + Icon = hobbyDto.Icon, + ResumeId = resume.ResumeId, + Order = order + }; + resumeRepository.AddHobby(hobbyEntity); + } + else + { + hobbyEntity.Name = hobbyDto.Name; + hobbyEntity.Description = hobbyDto.Description; + hobbyEntity.Icon = hobbyDto.Icon; + hobbyEntity.Order = order; + resumeRepository.UpdateHobby(hobbyEntity); + } + + resultEntities.Add(hobbyEntity); + order++; + } + + await resumeRepository.SaveChangesAsync(); + + return new AboutDto + { + About = resume.About, + Hobbies = mapper.Map>(resultEntities) + }; + } + + public async Task UpsertContactAsync(int candidateId, CandidateSocialLinksDto contactDto) + { + var resume = await resumeRepository.GetCandidateWithSocialLinksAsync(candidateId) + ?? throw new KeyNotFoundException($"Resume with candidate id {candidateId} not found."); + + if (!string.IsNullOrWhiteSpace(contactDto.Title)) + { + resume.Title = contactDto.Title; + resumeRepository.UpdateResume(resume); + } + + if (contactDto.Candidate != null && resume.Candidate != null) + { + resume.Candidate.FirstName = contactDto.Candidate.FirstName; + resume.Candidate.LastName = contactDto.Candidate.LastName; + resume.Candidate.Email = contactDto.Candidate.Email; + resume.Candidate.Phone = contactDto.Candidate.Phone; + resume.Candidate.Address = contactDto.Candidate.Address; + + resumeRepository.UpdateCandidate(resume.Candidate); + } + + if (contactDto.SocialLinks != null) + { + if (resume.SocialLinks == null) + { + resume.SocialLinks = new SocialLinks + { + ResumeId = resume.ResumeId, + GitHub = contactDto.SocialLinks.GitHub, + Linkedin = contactDto.SocialLinks.Linkedin, + Instagram = contactDto.SocialLinks.Instagram, + Facebook = contactDto.SocialLinks.Facebook, + Twitter = contactDto.SocialLinks.Twitter, + PersonalWebsite = contactDto.SocialLinks.PersonalWebsite, + BlogUrl = contactDto.SocialLinks.BlogUrl + }; + resumeRepository.AddSocialLink(resume.SocialLinks); + } + else + { + resume.SocialLinks.GitHub = contactDto.SocialLinks.GitHub; + resume.SocialLinks.Linkedin = contactDto.SocialLinks.Linkedin; + resume.SocialLinks.Instagram = contactDto.SocialLinks.Instagram; + resume.SocialLinks.Facebook = contactDto.SocialLinks.Facebook; + resume.SocialLinks.Twitter = contactDto.SocialLinks.Twitter; + resume.SocialLinks.PersonalWebsite = contactDto.SocialLinks.PersonalWebsite; + resume.SocialLinks.BlogUrl = contactDto.SocialLinks.BlogUrl; + + resumeRepository.UpdateSocialLink(resume.SocialLinks); + } + } + + await resumeRepository.SaveChangesAsync(); + + var updatedContact = await resumeRepository.GetCandidateWithSocialLinksAsync(candidateId); + return mapper.Map(updatedContact); + } + + public async Task> UpsertSkillsAsync(int candidateId, IEnumerable skillDtos) + { + var resumeWithCollections = await GetOrCreateResumeWithCollectionsAsync(candidateId); + + UpsertSkills(resumeWithCollections, skillDtos.ToList()); + + await resumeRepository.SaveChangesAsync(); + + var updatedResume = await resumeRepository.GetByIdWithCollectionsAsync(resumeWithCollections.ResumeId); + return mapper.Map>(updatedResume?.Skills ?? []); + } + + public async Task> UpsertAcademicsAsync(int candidateId, IEnumerable academicDtos) + { + var resumeWithCollections = await GetOrCreateResumeWithCollectionsAsync(candidateId); + + UpsertAcademics(resumeWithCollections, academicDtos.ToList()); + + await resumeRepository.SaveChangesAsync(); + + var updatedResume = await resumeRepository.GetByIdWithCollectionsAsync(resumeWithCollections.ResumeId); + return mapper.Map>(updatedResume?.Academics ?? []); + } + + public async Task> UpsertExperiencesAsync(int candidateId, IEnumerable experienceDtos) + { + var resumeWithCollections = await GetOrCreateResumeWithCollectionsAsync(candidateId); + + UpsertExperiences(resumeWithCollections, experienceDtos.ToList()); + + await resumeRepository.SaveChangesAsync(); + + var updatedResume = await resumeRepository.GetByIdWithCollectionsAsync(resumeWithCollections.ResumeId); + return mapper.Map>(updatedResume?.Experiences ?? []); + } + + public async Task> UpsertCertificationsAsync(int candidateId, IEnumerable certificationDtos) + { + var resumeWithCollections = await GetOrCreateResumeWithCollectionsAsync(candidateId); + + UpsertCertifications(resumeWithCollections, certificationDtos.ToList()); + + await resumeRepository.SaveChangesAsync(); + + var updatedResume = await resumeRepository.GetByIdWithCollectionsAsync(resumeWithCollections.ResumeId); + return mapper.Map>(updatedResume?.Certifications ?? []); + } + + #region Private Helpers + + private async Task GetOrCreateResumeWithCollectionsAsync(int candidateId) + { + var resume = await resumeRepository.GetLatestResumeForCandidateAsync(candidateId, includeOtherData: false); + + if (resume == null) + { + resume = new Resume + { + CandidateId = candidateId, + About = string.Empty, + Order = 1 + }; + + resumeRepository.AddResume(resume); + await resumeRepository.SaveChangesAsync(); + } + + return await resumeRepository.GetByIdWithCollectionsAsync(resume.ResumeId) + ?? throw new InvalidOperationException("Failed to reload resume with collections."); + } + + private void UpsertSkills(Resume resume, ICollection skillDtos) + { + var existingSkills = resume.Skills.ToList(); + var incomingIds = skillDtos.Where(s => s.SkillId > 0).Select(s => s.SkillId).ToHashSet(); + + foreach (var existing in existingSkills) + { + if (!incomingIds.Contains(existing.SkillId)) + { + resumeRepository.RemoveSkill(existing); + } + } + + foreach (var skillDto in skillDtos) + { + var skillEntity = skillDto.SkillId > 0 + ? existingSkills.FirstOrDefault(s => s.SkillId == skillDto.SkillId) + : null; + + if (skillEntity == null) + { + resumeRepository.AddSkill(new Skill + { + Name = skillDto.Name, + Description = skillDto.Description, + ProficiencyLevel = skillDto.ProficiencyLevel, + ResumeId = resume.ResumeId + }); + } + else + { + skillEntity.Name = skillDto.Name; + skillEntity.Description = skillDto.Description; + skillEntity.ProficiencyLevel = skillDto.ProficiencyLevel; + resumeRepository.UpdateSkill(skillEntity); + } + } + } + + private void UpsertAcademics(Resume resume, ICollection academicDtos) + { + var existingAcademics = resume.Academics.ToList(); + var incomingIds = academicDtos.Where(a => a.AcademicId > 0).Select(a => a.AcademicId).ToHashSet(); + + foreach (var existing in existingAcademics) + { + if (!incomingIds.Contains(existing.AcademicId)) + { + resumeRepository.RemoveAcademic(existing); + } + } + + foreach (var academicDto in academicDtos) + { + var academicEntity = academicDto.AcademicId > 0 + ? existingAcademics.FirstOrDefault(a => a.AcademicId == academicDto.AcademicId) + : null; + + if (academicEntity == null) + { + resumeRepository.AddAcademic(new Academic + { + Institution = academicDto.Institution, + StartYear = academicDto.StartYear, + EndYear = academicDto.EndYear, + Degree = academicDto.Degree, + DegreeSpecialization = academicDto.DegreeSpecialization, + ResumeId = resume.ResumeId + }); + } + else + { + academicEntity.Institution = academicDto.Institution; + academicEntity.StartYear = academicDto.StartYear; + academicEntity.EndYear = academicDto.EndYear; + academicEntity.Degree = academicDto.Degree; + academicEntity.DegreeSpecialization = academicDto.DegreeSpecialization; + resumeRepository.UpdateAcademic(academicEntity); + } + } + } + + private void UpsertExperiences(Resume resume, ICollection experienceDtos) + { + var existingExperiences = resume.Experiences.ToList(); + var incomingIds = experienceDtos.Where(e => e.ExperienceId > 0).Select(e => e.ExperienceId).ToHashSet(); + + foreach (var existing in existingExperiences) + { + if (!incomingIds.Contains(existing.ExperienceId)) + { + foreach (var detail in existing.Details.ToList()) + { + resumeRepository.RemoveExperienceDetails(detail); + } + resumeRepository.RemoveExperience(existing); + } + } + + foreach (var experienceDto in experienceDtos) + { + var experienceEntity = experienceDto.ExperienceId > 0 + ? existingExperiences.FirstOrDefault(e => e.ExperienceId == experienceDto.ExperienceId) + : null; + + if (experienceEntity == null) + { + experienceEntity = new Experience + { + Title = experienceDto.Title, + Description = experienceDto.Description, + Company = experienceDto.Company, + Location = experienceDto.Location ?? string.Empty, + StartDate = experienceDto.StartDate ?? DateTime.UtcNow, + EndDate = experienceDto.EndDate, + ResumeId = resume.ResumeId + }; + resumeRepository.AddExperience(experienceEntity); + + var detailOrder = 1; + foreach (var detailDto in experienceDto.Details) + { + resumeRepository.AddExperienceDetails(new ExperienceDetails + { + Details = detailDto.Details, + Order = detailOrder++, + Experience = experienceEntity + }); + } + } + else + { + experienceEntity.Title = experienceDto.Title; + experienceEntity.Description = experienceDto.Description; + experienceEntity.Company = experienceDto.Company; + if (!string.IsNullOrWhiteSpace(experienceDto.Location)) + experienceEntity.Location = experienceDto.Location; + if (experienceDto.StartDate.HasValue) + experienceEntity.StartDate = experienceDto.StartDate.Value; + experienceEntity.EndDate = experienceDto.EndDate; + + resumeRepository.UpdateExperience(experienceEntity); + UpsertExperienceDetails(experienceEntity, experienceDto.Details); + } + } + } + + private void UpsertExperienceDetails(Experience experience, ICollection detailDtos) + { + var existingDetails = experience.Details.ToList(); + var incomingIds = detailDtos.Where(d => d.Id > 0).Select(d => d.Id).ToHashSet(); + + foreach (var existing in existingDetails) + { + if (!incomingIds.Contains(existing.Id)) + { + resumeRepository.RemoveExperienceDetails(existing); + } + } + + var order = 1; + foreach (var detailDto in detailDtos) + { + var detailEntity = detailDto.Id > 0 + ? existingDetails.FirstOrDefault(d => d.Id == detailDto.Id) + : null; + + if (detailEntity == null) + { + resumeRepository.AddExperienceDetails(new ExperienceDetails + { + Details = detailDto.Details, + Order = order, + ExperienceId = experience.ExperienceId + }); + } + else + { + detailEntity.Details = detailDto.Details; + detailEntity.Order = order; + resumeRepository.UpdateExperienceDetails(detailEntity); + } + order++; + } + } + + private void UpsertCertifications(Resume resume, ICollection certificationDtos) + { + var existingCertifications = resume.Certifications.ToList(); + var incomingIds = certificationDtos.Where(c => c.CertificationId > 0).Select(c => c.CertificationId).ToHashSet(); + + foreach (var existing in existingCertifications) + { + if (!incomingIds.Contains(existing.CertificationId)) + { + resumeRepository.RemoveCertification(existing); + } + } + + foreach (var certDto in certificationDtos) + { + var existingCert = certDto.CertificationId > 0 + ? existingCertifications.FirstOrDefault(c => c.CertificationId == certDto.CertificationId) + : null; + + if (existingCert == null) + { + resumeRepository.AddCertification(new Certification + { + CertificationName = certDto.CertificationName, + IssuingOrganization = certDto.IssuingOrganization, + CertificationLink = certDto.CertificationLink, + IssueDate = certDto.IssueDate, + ExpiryDate = certDto.ExpiryDate, + ResumeId = resume.ResumeId + }); + } + else + { + existingCert.CertificationName = certDto.CertificationName; + existingCert.IssuingOrganization = certDto.IssuingOrganization; + existingCert.CertificationLink = certDto.CertificationLink; + existingCert.IssueDate = certDto.IssueDate; + existingCert.ExpiryDate = certDto.ExpiryDate; + resumeRepository.UpdateCertification(existingCert); + } + } + } + + #endregion + } +} diff --git a/PortBlog.API/Services/AuthService.cs b/PortBlog.API/Services/AuthService.cs index ae97e58..1ae4899 100644 --- a/PortBlog.API/Services/AuthService.cs +++ b/PortBlog.API/Services/AuthService.cs @@ -56,12 +56,19 @@ namespace PortBlog.API.Services /// The generated JWT access token as a string. public string GenerateAccessToken(string username) { - var claims = new[] + var candidate = context.Candidates.FirstOrDefault(c => c.Email == username); + + var claims = new List { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, "Admin") }; + if (candidate != null) + { + claims.Add(new Claim("CandidateId", candidate.CandidateId.ToString())); + } + var jwtKey = configuration["Jwt:Key"]; if (string.IsNullOrEmpty(jwtKey)) throw new InvalidOperationException("JWT key is not configured."); diff --git a/PortBlog.API/Services/Contracts/IAdminService.cs b/PortBlog.API/Services/Contracts/IAdminService.cs new file mode 100644 index 0000000..4f585c3 --- /dev/null +++ b/PortBlog.API/Services/Contracts/IAdminService.cs @@ -0,0 +1,37 @@ +using System.Security.Claims; +using PortBlog.API.Models; + +namespace PortBlog.API.Services.Contracts +{ + /// + /// Service for administrative operations related to candidates, resumes, and their associated data. + /// + public interface IAdminService + { + int GetCandidateIdFromClaims(ClaimsPrincipal user); + + Task GetHobbiesAsync(int candidateId); + + Task GetContactAsync(int candidateId); + + Task GetResumeAsync(int candidateId); + + Task GetProjectsAsync(int candidateId); + + Task UpsertProjectAsync(int candidateId, ProjectDto projectDto); + + Task DeleteProjectAsync(int candidateId, int projectId); + + Task UpsertHobbiesAsync(int candidateId, AboutDto aboutDto); + + Task> UpsertSkillsAsync(int candidateId, IEnumerable skillDtos); + + Task> UpsertAcademicsAsync(int candidateId, IEnumerable academicDtos); + + Task> UpsertExperiencesAsync(int candidateId, IEnumerable experienceDtos); + + Task> UpsertCertificationsAsync(int candidateId, IEnumerable certificationDtos); + + Task UpsertContactAsync(int candidateId, CandidateSocialLinksDto contactDto); + } +} diff --git a/PortBlog.Tests/PortBlog.Tests.csproj b/PortBlog.Tests/PortBlog.Tests.csproj new file mode 100644 index 0000000..db296aa --- /dev/null +++ b/PortBlog.Tests/PortBlog.Tests.csproj @@ -0,0 +1,21 @@ + + + + net10.0 + enable + enable + false + + + + + + + + + + + + + + \ No newline at end of file From 4ebd93d39b427f6b4f34184d5672967fed54457d Mon Sep 17 00:00:00 2001 From: Bangara Raju Kottedi Date: Sun, 15 Feb 2026 13:22:48 +0530 Subject: [PATCH 4/5] Update projects to .NET 10.0 and add Program doc entry Upgraded target frameworks to .NET 10.0 across multiple projects for latest compatibility. Added documentation for the auto-generated Program class in PortBlog.API.xml. No other functional changes. --- AesEncryption/AesEncryption.csproj | 2 +- PortBlog.API/PortBlog.API.csproj | 2 +- PortBlog.API/PortBlog.API.xml | 5 +++++ Shared/KBR.Cache/KBR.Cache.csproj | 2 +- Shared/KBR.Share.Lite/KBR.Shared.Lite.csproj | 2 +- Shared/KBR.Shared/KBR.Shared.csproj | 2 +- 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/AesEncryption/AesEncryption.csproj b/AesEncryption/AesEncryption.csproj index 63bbe21..1b38a68 100644 --- a/AesEncryption/AesEncryption.csproj +++ b/AesEncryption/AesEncryption.csproj @@ -2,7 +2,7 @@ Exe - net9.0 + net10.0 enable enable false diff --git a/PortBlog.API/PortBlog.API.csproj b/PortBlog.API/PortBlog.API.csproj index aabb708..cf49513 100644 --- a/PortBlog.API/PortBlog.API.csproj +++ b/PortBlog.API/PortBlog.API.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable True diff --git a/PortBlog.API/PortBlog.API.xml b/PortBlog.API/PortBlog.API.xml index 9fd26c2..24f7d12 100644 --- a/PortBlog.API/PortBlog.API.xml +++ b/PortBlog.API/PortBlog.API.xml @@ -696,5 +696,10 @@ The model to use when rendering the view. A task that represents the asynchronous operation. The task result contains the rendered view as a string. + + + Auto-generated public partial Program class for top-level statement apps. + + diff --git a/Shared/KBR.Cache/KBR.Cache.csproj b/Shared/KBR.Cache/KBR.Cache.csproj index a274065..2c97411 100644 --- a/Shared/KBR.Cache/KBR.Cache.csproj +++ b/Shared/KBR.Cache/KBR.Cache.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable diff --git a/Shared/KBR.Share.Lite/KBR.Shared.Lite.csproj b/Shared/KBR.Share.Lite/KBR.Shared.Lite.csproj index 2c2f89b..22badd1 100644 --- a/Shared/KBR.Share.Lite/KBR.Shared.Lite.csproj +++ b/Shared/KBR.Share.Lite/KBR.Shared.Lite.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable diff --git a/Shared/KBR.Shared/KBR.Shared.csproj b/Shared/KBR.Shared/KBR.Shared.csproj index 99ed569..5a714a1 100644 --- a/Shared/KBR.Shared/KBR.Shared.csproj +++ b/Shared/KBR.Shared/KBR.Shared.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable From 2533b5298f344519d42841bf6aadbe6e9bc6d67c Mon Sep 17 00:00:00 2001 From: Bangara Raju Kottedi Date: Sun, 15 Feb 2026 14:22:22 +0530 Subject: [PATCH 5/5] Support encrypted cache conn strings & update dependencies Moved DecryptConnectionString to KBR.Shared.Extensions for reuse and improved configuration access. Added Encryption property to CacheOptions and appsettings for conditional decryption of cache connection strings. Updated ServiceCollectionExtensions to decrypt SQL Server cache connection strings when needed. Upgraded NuGet packages across projects to latest .NET 8/10.0.x versions. Included minor code cleanups and OpenApiSecurityScheme improvements. --- PortBlog.API/PortBlog.API.csproj | 6 +++--- PortBlog.API/Program.cs | 7 +++---- PortBlog.API/appsettings.Development.json | 1 + PortBlog.Tests/PortBlog.Tests.csproj | 12 +++++++++--- .../Extensions/ServiceCollectionExtensions.cs | 8 +++++++- Shared/KBR.Cache/KBR.Cache.csproj | 16 ++++++++-------- Shared/KBR.Cache/Options/CacheOptions.cs | 2 ++ .../Extensions/ConfigurationExtensions.cs | 8 +++++--- Shared/KBR.Shared/KBR.Shared.csproj | 3 ++- 9 files changed, 40 insertions(+), 23 deletions(-) rename {PortBlog.API => Shared/KBR.Shared}/Extensions/ConfigurationExtensions.cs (83%) diff --git a/PortBlog.API/PortBlog.API.csproj b/PortBlog.API/PortBlog.API.csproj index cf49513..1abaca1 100644 --- a/PortBlog.API/PortBlog.API.csproj +++ b/PortBlog.API/PortBlog.API.csproj @@ -10,10 +10,10 @@ - - + + - + diff --git a/PortBlog.API/Program.cs b/PortBlog.API/Program.cs index 1389589..b31ba14 100644 --- a/PortBlog.API/Program.cs +++ b/PortBlog.API/Program.cs @@ -12,7 +12,7 @@ using PortBlog.API.Middleware; using Serilog; using System.Reflection; using System.Text; - +using KBR.Shared.Extensions; var builder = WebApplication.CreateBuilder(args); @@ -131,14 +131,13 @@ builder.Services.AddSwaggerGen(c => Scheme = "ApiKeyScheme" }); - var key = new OpenApiSecurityScheme() + var key = new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "ApiKey" - }, - In = ParameterLocation.Header + } }; // JWT Bearer Security Definition diff --git a/PortBlog.API/appsettings.Development.json b/PortBlog.API/appsettings.Development.json index 8598e30..1f73a69 100644 --- a/PortBlog.API/appsettings.Development.json +++ b/PortBlog.API/appsettings.Development.json @@ -6,6 +6,7 @@ }, "Cache": { "ConnectionString": "SERVER=192.168.0.197; DATABASE=cv_blog; UID=PortBlogDevUser; PWD=p@$$w0rd1234;Allow User Variables=true;", + "Encryption": "false", "Provider": "SqlServer" }, "Jwt": { diff --git a/PortBlog.Tests/PortBlog.Tests.csproj b/PortBlog.Tests/PortBlog.Tests.csproj index db296aa..163250f 100644 --- a/PortBlog.Tests/PortBlog.Tests.csproj +++ b/PortBlog.Tests/PortBlog.Tests.csproj @@ -8,10 +8,16 @@ - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Shared/KBR.Cache/Extensions/ServiceCollectionExtensions.cs b/Shared/KBR.Cache/Extensions/ServiceCollectionExtensions.cs index 9233798..6661a32 100644 --- a/Shared/KBR.Cache/Extensions/ServiceCollectionExtensions.cs +++ b/Shared/KBR.Cache/Extensions/ServiceCollectionExtensions.cs @@ -1,5 +1,6 @@ using KBR.Cache.Constants; using KBR.Cache.Options; +using KBR.Shared.Extensions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -20,9 +21,14 @@ namespace KBR.Cache.Extensions } else if (cacheOptions.Provider == CacheProviders.SqlServer) { + var connectionString = cacheOptions.ConnectionString; + if ((bool)cacheOptions.Encryption) + { + connectionString = configuration.DecryptConnectionString(connectionString); + } services.AddDistributedMySqlCache(options => { - options.ConnectionString = cacheOptions.ConnectionString; + options.ConnectionString = connectionString; options.TableName = "Cache"; }); } diff --git a/Shared/KBR.Cache/KBR.Cache.csproj b/Shared/KBR.Cache/KBR.Cache.csproj index 2c97411..9e1d787 100644 --- a/Shared/KBR.Cache/KBR.Cache.csproj +++ b/Shared/KBR.Cache/KBR.Cache.csproj @@ -7,14 +7,14 @@ - - - - - - - - + + + + + + + + diff --git a/Shared/KBR.Cache/Options/CacheOptions.cs b/Shared/KBR.Cache/Options/CacheOptions.cs index 4f0c502..b90a250 100644 --- a/Shared/KBR.Cache/Options/CacheOptions.cs +++ b/Shared/KBR.Cache/Options/CacheOptions.cs @@ -4,6 +4,8 @@ { public string Provider { get; set; } = null!; + public bool? Encryption { get; set; } = false; + public string? ConnectionString { get; set; } } } diff --git a/PortBlog.API/Extensions/ConfigurationExtensions.cs b/Shared/KBR.Shared/Extensions/ConfigurationExtensions.cs similarity index 83% rename from PortBlog.API/Extensions/ConfigurationExtensions.cs rename to Shared/KBR.Shared/Extensions/ConfigurationExtensions.cs index dd0763a..7a026c5 100644 --- a/PortBlog.API/Extensions/ConfigurationExtensions.cs +++ b/Shared/KBR.Shared/Extensions/ConfigurationExtensions.cs @@ -1,12 +1,14 @@ -using System.Security.Cryptography; +using Microsoft.Extensions.Configuration; +using System.Security.Cryptography; -namespace PortBlog.API.Extensions +namespace KBR.Shared.Extensions { public static class ConfigurationExtensions { public static string DecryptConnectionString(this IConfiguration configuration, string encryptedConnectionString) { - string keyBase64 = configuration.GetValue("ConnectionStrings:Key").ToString(); + // Fix: Use GetSection and Value instead of GetValue (since GetValue is not available on IConfiguration) + string keyBase64 = configuration.GetSection("ConnectionStrings:Key").Value; string vectorBase64 = encryptedConnectionString.Split(":")[1]; string cipherText = encryptedConnectionString.Split(":")[0]; diff --git a/Shared/KBR.Shared/KBR.Shared.csproj b/Shared/KBR.Shared/KBR.Shared.csproj index 5a714a1..69ee995 100644 --- a/Shared/KBR.Shared/KBR.Shared.csproj +++ b/Shared/KBR.Shared/KBR.Shared.csproj @@ -7,7 +7,8 @@ - + +