diff --git a/AuthenticationMicroservice.csproj b/AuthenticationMicroservice.csproj index 174ada931eceb9b05dc4493a55dc53371dec1bde..000f7fbafd1625cc734f5897fc817954216f93bd 100644 --- a/AuthenticationMicroservice.csproj +++ b/AuthenticationMicroservice.csproj @@ -1,41 +1,44 @@ <Project Sdk="Microsoft.NET.Sdk.Web"> - <PropertyGroup> - <TargetFramework>net8.0</TargetFramework> - <Nullable>enable</Nullable> - <ImplicitUsings>enable</ImplicitUsings> - <UserSecretsId>73bbe79f-c176-4d01-8185-46859357e82a</UserSecretsId> - <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> - <DockerfileContext>.</DockerfileContext> - </PropertyGroup> + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <Nullable>enable</Nullable> + <ImplicitUsings>enable</ImplicitUsings> + <UserSecretsId>73bbe79f-c176-4d01-8185-46859357e82a</UserSecretsId> + <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> + <DockerfileContext>.</DockerfileContext> + </PropertyGroup> - <ItemGroup> - <PackageReference Include="AutoMapper" Version="12.0.1" /> - <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" /> - <PackageReference Include="BenchmarkDotNet" Version="0.13.5" /> - <PackageReference Include="LazyCache" Version="2.4.0" /> - <PackageReference Include="LazyCache.AspNetCore" Version="2.4.0" /> - <PackageReference Include="MailKit" Version="3.6.0" /> - <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0-preview.2.23153.2" /> - <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="8.0.0-preview.2.23153.2" /> - <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0-preview.1.23112.2" /> - <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0-preview.2.23128.3" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0-preview.2.23128.3"> - <PrivateAssets>all</PrivateAssets> - <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> - </PackageReference> - <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0-preview.2.23128.3" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-preview.2.23128.3" /> - <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0-preview.2.23128.3"> - <PrivateAssets>all</PrivateAssets> - <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> - </PackageReference> - <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" /> - <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> - <PackageReference Include="Polly" Version="7.2.3" /> - <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> - <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" /> - <PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.5.0" /> - </ItemGroup> + <ItemGroup> + <PackageReference Include="AutoMapper" Version="12.0.1"/> + <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0"/> + <PackageReference Include="Azure.Storage.Blobs" Version="12.16.0-beta.1"/> + <PackageReference Include="Azure.Storage.Common" Version="12.15.0-beta.1"/> + <PackageReference Include="BenchmarkDotNet" Version="0.13.5"/> + <PackageReference Include="LazyCache" Version="2.4.0"/> + <PackageReference Include="LazyCache.AspNetCore" Version="2.4.0"/> + <PackageReference Include="MailKit" Version="3.6.0"/> + <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0-preview.2.23153.2"/> + <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="8.0.0-preview.2.23153.2"/> + <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0-preview.1.23112.2"/> + <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0-preview.2.23128.3"/> + <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0-preview.2.23128.3"> + <PrivateAssets>all</PrivateAssets> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + </PackageReference> + <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0-preview.2.23128.3"/> + <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-preview.2.23128.3"/> + <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0-preview.2.23128.3"> + <PrivateAssets>all</PrivateAssets> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + </PackageReference> + <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1"/> + <PackageReference Include="Newtonsoft.Json" Version="13.0.3"/> + <PackageReference Include="Polly" Version="7.2.3"/> + <PackageReference Include="SixLabors.ImageSharp" Version="3.0.1"/> + <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0"/> + <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0"/> + <PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.5.0"/> + </ItemGroup> </Project> diff --git a/Constants.cs b/Constants.cs index f5bc0e9b484bb462afcaba88385706b3f5d016a4..ac4c5231780f0e4bfe0bea1c8a7d8997f5e828a5 100644 --- a/Constants.cs +++ b/Constants.cs @@ -19,6 +19,11 @@ public abstract class Constants public const string ProfileSasToken = "profileSasToken"; } + public static class AzureBlobContainers + { + public const string ProfilePictures = "profile-pictures"; + } + public static class AuthorizationPolicies { public const string HasUserId = "HasUserId"; diff --git a/Controllers/AuthenticationController.cs b/Controllers/AuthenticationController.cs index 49dccd82fbd8cd6efb491fb0fb0e0e1bdab33d38..179127f30b1dda1f7ae7853bdd7604f0a5e4a2c3 100644 --- a/Controllers/AuthenticationController.cs +++ b/Controllers/AuthenticationController.cs @@ -18,11 +18,11 @@ using Swashbuckle.AspNetCore.Annotations; [ApiController] public class AuthController : BaseAuthController { + private readonly IAppCache _memoryCache; private readonly IAuthService _authService; + private readonly IUserService _userService; private readonly IEmailService _emailService; - private readonly IAppCache _memoryCache; private readonly IRefreshTokenService _refreshTokenService; - private readonly IUserService _userService; public AuthController(IAppCache memoryCache, IAuthService authService, IRefreshTokenService refreshTokenService, IUserService userService, IEmailService emailService) @@ -100,6 +100,8 @@ public class AuthController : BaseAuthController { try { + if (string.IsNullOrWhiteSpace(request.Password) || string.IsNullOrWhiteSpace(request.ConfirmPassword)) + return BadRequest("Please enter a password."); SecurityHelper.EnsurePasswordComplexity(request.Password, request.ConfirmPassword); await _authService.SetPassword(request); } @@ -252,4 +254,13 @@ public class AuthController : BaseAuthController return Ok(null); } + + [HttpPost("UploadProfilePicture")] + [Consumes("multipart/form-data")] + public async Task<ActionResult<ResponseEnvelope<string>>> UploadProfilePicture(IFormFile? profilePicture) + { + if (profilePicture == null) + return BadRequest("Please upload a proper image."); + return Ok(await _userService.UploadProfilePicture(UserId, profilePicture)); + } } \ No newline at end of file diff --git a/Helpers/ResponseOperationFilter.cs b/Helpers/ResponseOperationFilter.cs index 4ade9a3fc1a0907e8ecbbc4d137b29c0bc7ca127..7b09a261d29d19773874dce87b3e1d6ae3cec358 100644 --- a/Helpers/ResponseOperationFilter.cs +++ b/Helpers/ResponseOperationFilter.cs @@ -28,8 +28,7 @@ public class ResponseOperationFilter : IOperationFilter operation.Responses.Add("403", new OpenApiResponse {Description = "Forbidden"}); if (authAttributes != null && authorizeAttributes.Any() && anonAttributes != null && !anonAttributes.Any()) - { - operation.Security.Add(new OpenApiSecurityRequirement() + operation.Security.Add(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme @@ -38,12 +37,11 @@ public class ResponseOperationFilter : IOperationFilter { Id = "Bearer", Type = ReferenceType.SecurityScheme - }, + } }, new List<string>() } }); - } var apiTokenAttributes = context.MethodInfo.DeclaringType?.GetCustomAttributes(true) .Union(context.MethodInfo.GetCustomAttributes(true)) @@ -59,12 +57,11 @@ public class ResponseOperationFilter : IOperationFilter return; #pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. - Constants.Roles[] roles = (Constants.Roles[]) roleField.GetValue(apiTokenAttributes.First()); + var roles = (Constants.Roles[]) roleField.GetValue(apiTokenAttributes.First()); #pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. if (roles != null && roles.Contains(Constants.Roles.Api)) - { - operation.Security.Add(new OpenApiSecurityRequirement() + operation.Security.Add(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme @@ -73,17 +70,13 @@ public class ResponseOperationFilter : IOperationFilter { Id = "Authentication-API-Key", Type = ReferenceType.SecurityScheme - }, + } }, new List<string>() } }); - } - if (roles != null) - { - operation.Description += "Required Roles: " + string.Join(", ", roles); - } + if (roles != null) operation.Description += "Required Roles: " + string.Join(", ", roles); } } } \ No newline at end of file diff --git a/Middleware/ExceptionMiddleware.cs b/Middleware/ExceptionMiddleware.cs index 0cdee17b2cf5dd68e10a66959b3bbceed37f15fb..b181b7ce31514cab68805894aa6667544f38011e 100644 --- a/Middleware/ExceptionMiddleware.cs +++ b/Middleware/ExceptionMiddleware.cs @@ -2,6 +2,7 @@ namespace AuthenticationMicroservice.Middleware; using System.Net; using Exceptions; +using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; public class ExceptionMiddleware @@ -48,7 +49,7 @@ public class ExceptionMiddleware logger.LogWarning(ex.Message); break; - case Microsoft.EntityFrameworkCore.DbUpdateException dbex: + case DbUpdateException dbex: envelope = new ResponseEnvelope<object>(dbex, userMessage: "Database Error has occurred. Please try again or report the issue."); context.Response.StatusCode = (int) HttpStatusCode.InternalServerError; @@ -85,8 +86,6 @@ public class ResponseEnvelope public class ResponseEnvelope<T> : ResponseEnvelope { - public new T? Data { get; set; } - public ResponseEnvelope() { } @@ -94,7 +93,7 @@ public class ResponseEnvelope<T> : ResponseEnvelope public ResponseEnvelope(Exception ex, int statusCode = 400, string? userMessage = null) : this( new List<ErrorDetails> { - new ErrorDetails + new() { Message = ex.Message, InnerMessage = ex.InnerException?.Message, @@ -125,6 +124,8 @@ public class ResponseEnvelope<T> : ResponseEnvelope StatusCode = statusCode; } + public new T? Data { get; set; } + public override string ToString() { return JsonConvert.SerializeObject(this); diff --git a/Middleware/SwaggerAuthMiddleware.cs b/Middleware/SwaggerAuthMiddleware.cs index fd3f5b5152f30a52dc9f728610ba6cffe6e4a563..0ed8341f367692c93f95d3228d69d8e7ab2b310b 100644 --- a/Middleware/SwaggerAuthMiddleware.cs +++ b/Middleware/SwaggerAuthMiddleware.cs @@ -9,7 +9,7 @@ public class SwaggerAuthMiddleware public SwaggerAuthMiddleware(RequestDelegate next) { - this._next = next; + _next = next; } public async Task InvokeAsync(HttpContext context) diff --git a/Models/AuthenticationDbContext.cs b/Models/AuthenticationDbContext.cs index 0fcf1477bdeac4b962150968970d7946206de86c..b720a49a081a3d4bc12f1f5d79c21ddd250ad967 100644 --- a/Models/AuthenticationDbContext.cs +++ b/Models/AuthenticationDbContext.cs @@ -9,11 +9,13 @@ public class AuthenticationDbContext : DbContext { public static string ConnectionStringName = "DbConnectionString"; - public AuthenticationDbContext(DbContextOptions<AuthenticationDbContext> options) : base(options) { } + public AuthenticationDbContext(DbContextOptions<AuthenticationDbContext> options) : base(options) + { + } public DbSet<User> User { get; set; } = null!; public DbSet<RefreshToken> RefreshToken { get; set; } = null!; - + protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); diff --git a/Program.cs b/Program.cs index 1fd84ed0e9f682638e1e717a0299312272572a24..b99b65587160433dc59c51b8613f2c080f246319 100644 --- a/Program.cs +++ b/Program.cs @@ -24,8 +24,9 @@ builder.Configuration.AddJsonFile("appsettings.Development.json", true, true); builder.Services.Configure<EmailConfig>(builder.Configuration.GetSection("EmailConfig")); builder.Services.Configure<TokenSettings>(builder.Configuration.GetSection("TokenSettings")); builder.Services.AddDbContext<AuthenticationDbContext>(opt => - opt.UseSqlServer(builder.Configuration.GetConnectionString("AuthenticationDb") ?? + opt.UseSqlServer(builder.Configuration.GetConnectionString("DbConnectionString") ?? throw new Exception("Could not connect to database."))); +builder.Services.Configure<ConnectionStrings>(builder.Configuration.GetSection("ConnectionStrings")); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo {Title = "AuthenticationMicroserviceAPI", Version = "v1"}); @@ -104,8 +105,11 @@ var mapperConfig = new MapperConfiguration(mc => { mc.AddProfile(new AutoMapperP var mapper = mapperConfig.CreateMapper(); builder.Services.AddSingleton(mapper); +// Add repositories from /Repositories builder.Services.AddTransient(typeof(IBaseRepository<>), typeof(BaseRepository<>)); +// Add services from /Services +builder.Services.AddTransient<IStorageService, StorageService>(); builder.Services.AddTransient<IUserService, UserService>(); builder.Services.AddTransient<IRefreshTokenService, RefreshTokenService>(); builder.Services.AddTransient<IEmailService, EmailService>(); @@ -143,9 +147,6 @@ app.UseMiddleware<ExceptionMiddleware>(); app.UseHttpsRedirection(); app.UseOutputCache(); -app.UseEndpoints(endpoints => -{ - endpoints.MapControllers(); -}); +app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.Run(); \ No newline at end of file diff --git a/Repositories/BaseRepository.cs b/Repositories/BaseRepository.cs index 4d3cbe119492c06321afb4bc96e0370f5010997d..ace3136aed38c6aae6abd7c65ccd42e03039d855 100644 --- a/Repositories/BaseRepository.cs +++ b/Repositories/BaseRepository.cs @@ -26,8 +26,8 @@ public interface IBaseRepository<TEntity> where TEntity : class public sealed class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class { - private readonly AuthenticationDbContext _context; private readonly DbSet<TEntity> _dbSet; + private readonly AuthenticationDbContext _context; public BaseRepository(AuthenticationDbContext context) { @@ -47,12 +47,14 @@ public sealed class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEn public TEntity GetByIdThrowIfNull(int id) { - return GetById(id) ?? throw new AuthenticationException($"Item with ID {id} does not exist.", HttpStatusCode.NotFound); + return GetById(id) ?? + throw new AuthenticationException($"Item with ID {id} does not exist.", HttpStatusCode.NotFound); } public TEntity GetByIdThrowIfNull(Guid id) { - return GetById(id) ?? throw new AuthenticationException($"Item with ID {id} does not exist.", HttpStatusCode.NotFound); + return GetById(id) ?? + throw new AuthenticationException($"Item with ID {id} does not exist.", HttpStatusCode.NotFound); } public IQueryable<TEntity> GetAll() diff --git a/Services/AuthService.cs b/Services/AuthService.cs index a506085190bf80f7b2fba3a002803f91af263461..971c509af5d72e3fc434f5d42b62277fd03557e2 100644 --- a/Services/AuthService.cs +++ b/Services/AuthService.cs @@ -30,7 +30,8 @@ public class AuthService : IAuthService private readonly AuthenticationDbContext _context; private readonly IRefreshTokenService _refreshTokenService; - public AuthService(AuthenticationDbContext context, IEmailService emailService, IRefreshTokenService refreshTokenService) + public AuthService(AuthenticationDbContext context, IEmailService emailService, + IRefreshTokenService refreshTokenService) { _context = context; _emailService = emailService; @@ -62,7 +63,7 @@ public class AuthService : IAuthService throw new AuthenticationException("User not found.", HttpStatusCode.Unauthorized); return await GenerateAuthenticatedUser(user, oldRefreshToken); } - + public async Task<AuthenticatedUserDTO> GenerateAuthenticatedUser(User user, string? oldToken = null) { var newAccess = _refreshTokenService.CreateNewTokenForUser(user); diff --git a/Services/EmailService.cs b/Services/EmailService.cs index fe24bd48506a9566b99854ccf797343a30ce4b48..e19d1bf0560487a00b513fbe12ca5d1acf4b24d8 100644 --- a/Services/EmailService.cs +++ b/Services/EmailService.cs @@ -41,7 +41,8 @@ public class EmailService : IEmailService } catch (Exception ex) { - throw new AuthenticationException($"Failed to send email to: {to}. " + ex.Message, HttpStatusCode.InternalServerError); + throw new AuthenticationException($"Failed to send email to: {to}. " + ex.Message, + HttpStatusCode.InternalServerError); } } } \ No newline at end of file diff --git a/Services/StorageService.cs b/Services/StorageService.cs new file mode 100644 index 0000000000000000000000000000000000000000..b01487ec04e3391b13a0db907210e582fc7d43c7 --- /dev/null +++ b/Services/StorageService.cs @@ -0,0 +1,71 @@ +namespace AuthenticationMicroservice.Services; + +using System.Web; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Azure.Storage.Sas; +using Microsoft.Extensions.Options; +using Settings; + +public interface IStorageService +{ + Task<Uri> SaveImageAsJpgBlob(string containerName, string fileName, Stream input, + Dictionary<string, string>? metadata = null); + + string GetSasForFile(string containerName, string url, DateTimeOffset? expires = null); +} + +public class StorageService : IStorageService +{ + private readonly ConnectionStrings _connectionStrings; + + public StorageService(IOptions<ConnectionStrings> connectionStrings) + { + _connectionStrings = connectionStrings.Value; + } + + public string GetSasForFile(string containerName, string url, DateTimeOffset? expires = null) + { + url = GetFileFromUrl(url, containerName) ?? string.Empty; + if (string.IsNullOrWhiteSpace(url)) + return string.Empty; + var container = new BlobContainerClient(_connectionStrings.AzureBlobStorage, containerName); + var blob = container.GetBlobClient(url); + var urlWithSas = blob.GenerateSasUri(BlobSasPermissions.Read, DateTimeOffset.Now.AddHours(3)).ToString(); + return urlWithSas; + } + + public async Task<Uri> SaveImageAsJpgBlob(string containerName, string fileName, Stream input, + Dictionary<string, string>? metadata = null) + { + using var image = await Image.LoadAsync(input); + using var croppedImage = new MemoryStream(); + var clone = image.Clone(context => + context.Resize(new ResizeOptions {Mode = ResizeMode.Max, Size = new Size(1366, 768)})); + await clone.SaveAsJpegAsync(croppedImage); + croppedImage.Position = 0; + var blob = await GetBlobReference(containerName, fileName); + await blob.SetHttpHeadersAsync(new BlobHttpHeaders {ContentType = "image/jpeg"}); + await blob.UploadAsync(croppedImage); + return blob.Uri; + } + + private async Task<BlobClient> GetBlobReference(string? containerName, string blobName) + { + var container = new BlobContainerClient(_connectionStrings.AzureBlobStorage, containerName); + await container.CreateIfNotExistsAsync(); + var blob = container.GetBlobClient(blobName); + return blob; + } + + private static string? GetFileFromUrl(string url, string container) + { + if (string.IsNullOrEmpty(url)) + return null; + + var userDataContainerString = container + "/"; + var fileUrl = + url[(url.IndexOf(userDataContainerString, StringComparison.Ordinal) + userDataContainerString.Length)..]; + return HttpUtility.UrlDecode(fileUrl); + } +} \ No newline at end of file diff --git a/Services/UserService.cs b/Services/UserService.cs index 9a0e566eb5f39cd5a00ef023b209639764cf80d9..a329e88b7c5eb694cd08c004fad49b974c5ad7f1 100644 --- a/Services/UserService.cs +++ b/Services/UserService.cs @@ -14,19 +14,20 @@ public interface IUserService { Task<User> CreateUser(UserRegisterRequestDTO request); Task<string> UploadProfilePicture(int userId, IFormFile profilePicture); - Task<string> EditProfilePicture(int userId, IFormFile? profilePicture = null); List<UserDTO> GetListOfAllUsers(); } public class UserService : IUserService { private readonly IMapper _mapper; + private readonly IStorageService _storageService; private readonly IBaseRepository<User> _userRepo; - public UserService(IMapper mapper, IBaseRepository<User> userRepo) + public UserService(IMapper mapper, IBaseRepository<User> userRepo, IStorageService storageService) { _mapper = mapper; _userRepo = userRepo; + _storageService = storageService; } public async Task<User> CreateUser(UserRegisterRequestDTO request) @@ -50,18 +51,22 @@ public class UserService : IUserService return await _userRepo.CreateAndSaveAsync(newUser); } - public Task<string> UploadProfilePicture(int userId, IFormFile profilePicture) + public async Task<string> UploadProfilePicture(int userId, IFormFile profilePicture) { - throw new NotImplementedException(); - } - - public Task<string> EditProfilePicture(int userId, IFormFile? profilePicture = null) - { - throw new NotImplementedException(); + var user = _userRepo.GetByIdThrowIfNull(userId); + using var ms = new MemoryStream(); + await profilePicture.CopyToAsync(ms); + ms.Position = 0; + var fileName = $"{user.Id}/{user.FirstName}"; + var image = await _storageService.SaveImageAsJpgBlob(Constants.AzureBlobContainers.ProfilePictures, fileName, + ms); + user.ProfilePictureUrl = image.ToString(); + await _userRepo.UpdateAndSaveAsync(user); + return _storageService.GetSasForFile(Constants.AzureBlobContainers.ProfilePictures, image.ToString()); } public List<UserDTO> GetListOfAllUsers() { - return _mapper.ProjectTo<UserDTO>(_userRepo.GetAll()).ToList(); + return _mapper.ProjectTo<UserDTO>(_userRepo.GetAll().AsNoTracking()).ToList(); } } \ No newline at end of file diff --git a/Settings/ConnectionStrings.cs b/Settings/ConnectionStrings.cs new file mode 100644 index 0000000000000000000000000000000000000000..b39afcd908c698b79c5d634ce603ef11c5880156 --- /dev/null +++ b/Settings/ConnectionStrings.cs @@ -0,0 +1,7 @@ +namespace AuthenticationMicroservice.Settings; + +public class ConnectionStrings +{ + public string? DbConnectionString { get; set; } + public string? AzureBlobStorage { get; set; } +} \ No newline at end of file diff --git a/appsettings.json b/appsettings.json index 10f68b8c8b4f796baf8ddeee7551b6a52b9437cc..bc7d0aa4be83bf3cc276d7277220c8228ce6f327 100644 --- a/appsettings.json +++ b/appsettings.json @@ -5,5 +5,22 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" -} + "AllowedHosts": "*", + "ConnectionStrings": { + "DbConnectionString": "", + "AzureBlobStorage": "" + }, + "TokenSettings": { + "RefreshTokenValidityMinutes": 43200, + "AccessTokenValidityMinutes": 3600, + "RefreshTokenRandomNumbers": 32, + "Secret": "" + }, + "EmailConfig": { + "Email": "", + "Password": "" + }, + "Group17Website": { + "BaseUrl": "" + } +} \ No newline at end of file