Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/Bit.sln
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,22 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorDual.Shared", "Templa
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorDual.Web", "Templates\BlazorDual\Bit.BlazorDual\src\BlazorDual.Web\BlazorDual.Web.csproj", "{A9A5D4CF-F2A5-4088-93D2-7E5A28580B53}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".azure-devops", ".azure-devops", "{51FC3C7A-E553-4C98-B8EF-CD8DBEF08154}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{20C9DA20-C7DA-4842-9D90-085B57DEA880}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{677B433E-6E3F-4CEF-9EA3-2190D1EAD69C}"
ProjectSection(SolutionItems) = preProject
Templates\BlazorDual\Bit.BlazorDual\.github\workflows\cd.yml = Templates\BlazorDual\Bit.BlazorDual\.github\workflows\cd.yml
Templates\BlazorDual\Bit.BlazorDual\.github\workflows\ci.yml = Templates\BlazorDual\Bit.BlazorDual\.github\workflows\ci.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{B1EECB57-EEA6-4316-BC13-E6D9D6B297BE}"
ProjectSection(SolutionItems) = preProject
Templates\BlazorDual\Bit.BlazorDual\.azure-devops\workflows\cd.yml = Templates\BlazorDual\Bit.BlazorDual\.azure-devops\workflows\cd.yml
Templates\BlazorDual\Bit.BlazorDual\.azure-devops\workflows\ci.yml = Templates\BlazorDual\Bit.BlazorDual\.azure-devops\workflows\ci.yml
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1392,6 +1408,10 @@ Global
{FCD49D2B-5A28-4919-A334-A3F9E46B7495} = {C6624DE1-7886-444E-BB96-380B807593BD}
{51F3127E-6848-468F-A133-F4C67BEC0E24} = {C6624DE1-7886-444E-BB96-380B807593BD}
{A9A5D4CF-F2A5-4088-93D2-7E5A28580B53} = {C6624DE1-7886-444E-BB96-380B807593BD}
{51FC3C7A-E553-4C98-B8EF-CD8DBEF08154} = {C6624DE1-7886-444E-BB96-380B807593BD}
{20C9DA20-C7DA-4842-9D90-085B57DEA880} = {C6624DE1-7886-444E-BB96-380B807593BD}
{677B433E-6E3F-4CEF-9EA3-2190D1EAD69C} = {20C9DA20-C7DA-4842-9D90-085B57DEA880}
{B1EECB57-EEA6-4316-BC13-E6D9D6B297BE} = {51FC3C7A-E553-4C98-B8EF-CD8DBEF08154}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DA107107-478F-477A-872B-787CEA7DD9B8}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ jobs:
targetType: 'inline'
script: dotnet workload install wasm-tools

- task: FileTransform@1
displayName: Update appsettings.json
inputs:
fileType: 'json'
folderPath: './'
targetFiles: 'src/Client/Shared/appsettings.json'

- task: Bash@3
displayName: 'Build (To generate CSS/JS files)'
inputs:
Expand Down Expand Up @@ -164,7 +171,7 @@ jobs:
inputs:
fileType: 'json'
folderPath: './'
targetFiles: 'src/Client/Shared/wwwroot/appsettings.json'
targetFiles: 'src/Client/Shared/appsettings.json'

- task: Bash@3
displayName: 'Restore workloads'
Expand Down Expand Up @@ -231,7 +238,7 @@ jobs:
inputs:
fileType: 'json'
folderPath: './'
targetFiles: 'src/Client/Shared/wwwroot/appsettings.json'
targetFiles: 'src/Client/Shared/appsettings.json'

- task: Bash@3
displayName: 'Build (To generate CSS/JS files)'
Expand Down Expand Up @@ -287,7 +294,7 @@ jobs:
inputs:
fileType: 'json'
folderPath: './'
targetFiles: 'src/Client/Shared/wwwroot/appsettings.json'
targetFiles: 'src/Client/Shared/appsettings.json'

- task: Bash@3
displayName: 'Restore workloads'
Expand Down
15 changes: 11 additions & 4 deletions src/Templates/AdminPanel/Bit.AdminPanel/.github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ jobs:

- name: Restore workloads
run: dotnet workload restore src/Client/Web/AdminPanel.Client.Web.csproj -p:BlazorMode=BlazorWebAssembly -p:WebAppDeploymentType="${{ env.WEB_APP_DEPLOYMENT_TYPE }}"

- name: Update appsettings.json api server address
uses: microsoft/variable-substitution@v1
with:
files: 'src/Client/Shared/appsettings.json'
env:
ApiServerAddress: ${{ env.API_SERVER_ADDRESS }}

- name: Build (To generate CSS/JS files)
run: dotnet build src/Server/Api/AdminPanel.Server.Api.csproj -p:BlazorMode=BlazorWebAssembly -p:WebAppDeploymentType="${{ env.WEB_APP_DEPLOYMENT_TYPE }}" -p:Configuration=Release
Expand Down Expand Up @@ -134,7 +141,7 @@ jobs:
- name: Update appsettings.json api server address
uses: microsoft/variable-substitution@v1
with:
files: 'src/Client/Shared/wwwroot/appsettings.json'
files: 'src/Client/Shared/appsettings.json'
env:
ApiServerAddress: ${{ env.API_SERVER_ADDRESS }}

Expand Down Expand Up @@ -177,7 +184,7 @@ jobs:
- name: Update appsettings.json api server address
uses: microsoft/variable-substitution@v1
with:
files: 'src/Client/Shared/wwwroot/appsettings.json'
files: 'src/Client/Shared/appsettings.json'
env:
ApiServerAddress: ${{ env.API_SERVER_ADDRESS }}

Expand Down Expand Up @@ -216,7 +223,7 @@ jobs:
- name: Update appsettings.json api server address
uses: microsoft/variable-substitution@v1
with:
files: 'src/Client/Shared/wwwroot/appsettings.json'
files: 'src/Client/Shared/appsettings.json'
env:
ApiServerAddress: ${{ env.API_SERVER_ADDRESS }}

Expand Down Expand Up @@ -252,7 +259,7 @@ jobs:
- name: Update appsettings.json api server address
uses: microsoft/variable-substitution@v1
with:
files: 'src/Client/Shared/wwwroot/appsettings.json'
files: 'src/Client/Shared/appsettings.json'
env:
ApiServerAddress: ${{ env.API_SERVER_ADDRESS }}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@

<ItemGroup>

<Using Include="Microsoft.Extensions.Configuration" />
<Using Include="AdminPanel.Client.Shared.Components" />
<Using Include="AdminPanel.Client.Shared.Services.Implementations" />
<Using Include="AdminPanel.Client.Shared.Services.Contracts" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public static MauiAppBuilder CreateMauiAppBuilder()

builder
.UseMauiApp<App>()
.Configuration.AddJsonFile(new EmbeddedFileProvider(assembly), "wwwroot.appsettings.json", optional: false, false);
.Configuration.AddJsonFile(new EmbeddedFileProvider(assembly), "appsettings.json", optional: false, false);

var services = builder.Services;

Expand All @@ -32,7 +32,7 @@ public static MauiAppBuilder CreateMauiAppBuilder()
{
HttpClient httpClient = new(sp.GetRequiredService<AppHttpClientHandler>())
{
BaseAddress = new Uri($"{sp.GetRequiredService<IConfiguration>()["ApiServerAddress"]}")
BaseAddress = new Uri($"{sp.GetRequiredService<IConfiguration>().GetApiServerAddress()}")
};

return httpClient;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
<Content Remove="compilerconfig.json" />
<None Include="compilerconfig.json" />
<None Include="Shared\LoadingComponent.razor.scss" />
<Content Remove="wwwroot\appsettings.json" />
<EmbeddedResource Include="wwwroot\appsettings.json" />
<Content Remove="appsettings.json" />
<EmbeddedResource Include="appsettings.json" />

<PackageReference Include="Bit.BlazorUI" Version="4.9.6-pre-03" />
<PackageReference Include="Bit.BlazorUI.Charts" Version="4.9.6-pre-03" />
Expand Down Expand Up @@ -42,7 +42,6 @@
<Using Include="Microsoft.AspNetCore.Components" />
<Using Include="AdminPanel.Client.Shared.Services.Contracts" />
<Using Include="AdminPanel.Client.Shared.Services.Implementations" />
<Using Include="Microsoft.Extensions.Configuration" />
<Using Include="Microsoft.JSInterop" />
<Using Include="System.Net.Http.Json" />
<Using Include="System.Collections.Concurrent" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Microsoft.Extensions.Configuration;
public static class IConfigurationExtensions
{
public static string GetApiServerAddress(this IConfiguration configuration)
{
return configuration.GetValue<string?>("ApiServerAddress") ?? throw new InvalidOperationException("Could not find ApiServerAddress config");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private async Task Save()
{
_saveMessageType = BitMessageBarType.Error;

_saveMessage = string.Join(Environment.NewLine, e.Details.SelectMany(d => d.Errors).Select(e => e.Message));
_saveMessage = string.Join(Environment.NewLine, e.Payload.Details.SelectMany(d => d.Errors).Select(e => e.Message));
}
catch (KnownException e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ protected override async Task OnInitAsync()

var access_token = await StateService.GetValue($"{nameof(EditProfilePage)}-access_token", AuthTokenProvider.GetAcccessTokenAsync);

_profileImageUploadUrl = $"{GetBaseUrl()}Attachment/UploadProfileImage?access_token={access_token}";
_profileImageUrl = $"{GetBaseUrl()}Attachment/GetProfileImage?access_token={access_token}";
_profileImageUploadUrl = $"{Configuration.GetApiServerAddress()}Attachment/UploadProfileImage?access_token={access_token}";
_profileImageUrl = $"{Configuration.GetApiServerAddress()}Attachment/GetProfileImage?access_token={access_token}";
_profileImageRemoveUrl = $"Attachment/RemoveProfileImage?access_token={access_token}";
}
finally
Expand All @@ -38,15 +38,6 @@ protected override async Task OnInitAsync()
}
}

private string GetBaseUrl()
{
#if BlazorWebAssembly
return "/api/";
#else
return Configuration.GetValue<string>("ApiServerAddress") ?? string.Empty;
#endif
}

private async Task LoadEditProfileData()
{
_user = await StateService.GetValue($"{nameof(EditProfilePage)}-{nameof(_user)}", GetCurrentUser) ?? new();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private async Task DoSignUp()
catch (ResourceValidationException e)
{
_signUpMessageType = BitMessageBarType.Error;
_signUpMessage = string.Join(Environment.NewLine, e.Details.SelectMany(d => d.Errors).Select(e => e.Message));
_signUpMessage = string.Join(Environment.NewLine, e.Payload.Details.SelectMany(d => d.Errors).Select(e => e.Message));
}
catch (KnownException e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public partial class AppHttpClientHandler : HttpClientHandler

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Headers.Authorization is null && OperatingSystem.IsBrowser() is false)
if (request.Headers.Authorization is null)
{
var access_token = await _tokenProvider.GetAcccessTokenAsync();
if (access_token is not null)
Expand All @@ -34,13 +34,13 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
throw new UnauthorizedException();
}

if (response.IsSuccessStatusCode is false && response.Content.Headers.ContentType?.MediaType == "application/json")
if (response.IsSuccessStatusCode is false && response.Content.Headers.ContentType?.MediaType?.Contains("application/json", StringComparison.InvariantCultureIgnoreCase) is true)
{
if (response.Headers.TryGetValues("Request-ID", out IEnumerable<string>? values) && values is not null && values.Any())
{
RestExceptionPayload restError = await response.Content.ReadFromJsonAsync(AppJsonContext.Default.RestExceptionPayload, cancellationToken) ?? new();
RestErrorInfo restError = await response.Content.ReadFromJsonAsync(AppJsonContext.Default.RestErrorInfo, cancellationToken) ?? new();

Type exceptionType = typeof(RestExceptionPayload).Assembly.GetType(restError.ExceptionType ?? string.Empty) ?? typeof(UnknownException);
Type exceptionType = typeof(RestErrorInfo).Assembly.GetType(restError.ExceptionType ?? string.Empty) ?? typeof(UnknownException);

List<object> args = new()
{
Expand All @@ -51,7 +51,7 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage

if (exceptionType == typeof(ResourceValidationException))
{
args.Add(restError.Details);
args.Add(restError.Payload);
}

throw (Exception)(Activator.CreateInstance(exceptionType, args.ToArray()) ?? new Exception());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected override async Task OnInitAsync()
_isUserAuthenticated = await StateService.GetValue($"{nameof(Header)}-IsUserAuthenticated", AuthenticationStateProvider.IsUserAuthenticatedAsync);

var access_token = await StateService.GetValue($"{nameof(Header)}-access_token", AuthTokenProvider.GetAcccessTokenAsync);
_profileImageUrlBase = $"{GetBaseUrl()}Attachment/GetProfileImage?access_token={access_token}&file=";
_profileImageUrlBase = $"{Configuration.GetApiServerAddress()}Attachment/GetProfileImage?access_token={access_token}&file=";

SetProfileImageUrl();
}
Expand Down Expand Up @@ -131,15 +131,6 @@ private void SetBreadcrumbItems()
};
}

private string GetBaseUrl()
{
#if BlazorWebAssembly
return "/api/";
#else
return Configuration.GetValue<string>("ApiServerAddress") ?? string.Empty;
#endif
}

private async void VerifyUserIsAuthenticatedOrNot(Task<AuthenticationState> task)
{
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static WebAssemblyHost CreateHostBuilder(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault();

builder.Configuration.AddJsonStream(typeof(MainLayout).Assembly.GetManifestResourceStream("AdminPanel.Client.Shared.wwwroot.appsettings.json"));
builder.Configuration.AddJsonStream(typeof(MainLayout).Assembly.GetManifestResourceStream("AdminPanel.Client.Shared.appsettings.json"));

builder.Services.AddSingleton(sp => new HttpClient(sp.GetRequiredService<AppHttpClientHandler>()) { BaseAddress = new Uri($"{builder.HostEnvironment.BaseAddress}api/") });
builder.Services.AddScoped<LazyAssemblyLoader>();
Expand All @@ -55,7 +55,7 @@ public static WebAssemblyHost CreateHostBuilder(string[] args)
public static WebApplication CreateHostBuilder(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonStream(typeof(MainLayout).Assembly.GetManifestResourceStream("AdminPanel.Client.Shared.wwwroot.appsettings.json")!);
builder.Configuration.AddJsonStream(typeof(MainLayout).Assembly.GetManifestResourceStream("AdminPanel.Client.Shared.appsettings.json")!);
#if BlazorElectron
builder.WebHost.UseElectron(args);
builder.Services.AddElectron();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static void Add(IServiceCollection services, IConfiguration configuration
{
HttpClient httpClient = new(sp.GetRequiredService<AppHttpClientHandler>())
{
BaseAddress = new Uri($"{sp.GetRequiredService<IConfiguration>()["ApiServerAddress"]}")
BaseAddress = new Uri($"{sp.GetRequiredService<IConfiguration>().GetApiServerAddress()}")
};

return httpClient;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<Using Include="AdminPanel.Shared.Exceptions" />
<Using Include="AdminPanel.Shared.Resources" />
<Using Include="Microsoft.Extensions.Localization" />
<Using Include="Microsoft.Extensions.Configuration" />
<Using Include="AdminPanel.Shared.Infra" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public static IServiceCollection AddJwt(this IServiceCollection services, IConfi
{
var certificatePath = Path.Combine(Directory.GetCurrentDirectory(), "IdentityCertificate.pfx");
RSA? rsaPrivateKey;
using (X509Certificate2 signingCert = new X509Certificate2(certificatePath, appsettings.JwtSettings.IdentityCertificatePassword))
using (X509Certificate2 signingCert = new X509Certificate2(certificatePath, appsettings.JwtSettings.IdentityCertificatePassword, X509KeyStorageFlags.EphemeralKeySet))
{
rsaPrivateKey = signingCert.GetRSAPrivateKey();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public async Task Invoke(HttpContext context, IHostEnvironment webHostEnvironmen
message = localizer[message];
}

RestExceptionPayload restExceptionPayload = new RestExceptionPayload
RestErrorInfo restExceptionPayload = new RestErrorInfo
{
Key = key,
Message = message,
Expand All @@ -47,7 +47,7 @@ public async Task Invoke(HttpContext context, IHostEnvironment webHostEnvironmen

if (exception is ResourceValidationException validationException)
{
restExceptionPayload.Details = validationException.Details;
restExceptionPayload.Payload = validationException.Payload;
}

context.Response.StatusCode = statusCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public async Task<SignInResponseDto> GenerateToken(User user)
{
var certificatePath = Path.Combine(Directory.GetCurrentDirectory(), "IdentityCertificate.pfx");
RSA? rsaPrivateKey;
using (X509Certificate2 signingCert = new X509Certificate2(certificatePath, _appSettings.JwtSettings.IdentityCertificatePassword))
using (X509Certificate2 signingCert = new X509Certificate2(certificatePath, _appSettings.JwtSettings.IdentityCertificatePassword, X509KeyStorageFlags.EphemeralKeySet))
{
rsaPrivateKey = signingCert.GetRSAPrivateKey();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.OData;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.DependencyInjection;
#if BlazorWebAssembly
using AdminPanel.Client.Web.Services.Implementations;
using AdminPanel.Client.Shared.Services.Implementations;
Expand Down Expand Up @@ -60,16 +61,7 @@ public static void Add(IServiceCollection services, IWebHostEnvironment env, ICo
{
options.InvalidModelStateResponseFactory = context =>
{
throw new ResourceValidationException(context.ModelState
.Select(ms => new ResourceValidationExceptionPayload
{
Property = ms.Key,
Errors = ms.Value!.Errors.Select(e => new ResourceValidationExceptionPayloadError
{
Key = e.ErrorMessage,
Message = e.ErrorMessage
})
}).ToList());
throw new ResourceValidationException(context.ModelState.Select(ms => (ms.Key, ms.Value!.Errors.Select(e => new LocalizedString(e.ErrorMessage, e.ErrorMessage)).ToArray())).ToArray());
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace AdminPanel.Shared.Dtos;
[JsonSerializable(typeof(SignInResponseDto))]
[JsonSerializable(typeof(SignUpRequestDto))]
[JsonSerializable(typeof(EditUserDto))]
[JsonSerializable(typeof(RestExceptionPayload))]
[JsonSerializable(typeof(RestErrorInfo))]
[JsonSerializable(typeof(EmailConfirmedRequestDto))]
[JsonSerializable(typeof(SendConfirmationEmailRequestDto))]
[JsonSerializable(typeof(SendResetPasswordEmailRequestDto))]
Expand Down
Loading