diff --git a/Oqtane.Client/Modules/Controls/FileManager.razor b/Oqtane.Client/Modules/Controls/FileManager.razor index 1bbe4581..a6a863aa 100644 --- a/Oqtane.Client/Modules/Controls/FileManager.razor +++ b/Oqtane.Client/Modules/Controls/FileManager.razor @@ -4,6 +4,7 @@ @inject IFolderService FolderService @inject IFileService FileService @inject ISettingService SettingService +@inject IUserService UserService @inject IStringLocalizer Localizer @inject IStringLocalizer SharedLocalizer @@ -344,7 +345,7 @@ _message = string.Empty; var interop = new Interop(JSRuntime); var uploads = await interop.GetFiles(_fileinputid); - + if (uploads.Length > 0) { string restricted = ""; @@ -370,7 +371,12 @@ // upload the files var posturl = Utilities.TenantUrl(PageState.Alias, "/api/file/upload"); var folder = (Folder == Constants.PackagesFolder) ? Folder : FolderId.ToString(); - await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken); + var jwt = ""; + if (PageState.Runtime == Shared.Runtime.Hybrid) + { + jwt = await UserService.GetTokenAsync(); + } + await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken, jwt); // uploading is asynchronous so we need to poll to determine if uploads are completed var success = true; diff --git a/Oqtane.Client/UI/Interop.cs b/Oqtane.Client/UI/Interop.cs index 9ed3f91e..cc379dc6 100644 --- a/Oqtane.Client/UI/Interop.cs +++ b/Oqtane.Client/UI/Interop.cs @@ -198,13 +198,13 @@ namespace Oqtane.UI } } - public Task UploadFiles(string posturl, string folder, string id, string antiforgerytoken) + public Task UploadFiles(string posturl, string folder, string id, string antiforgerytoken, string jwt) { try { _jsRuntime.InvokeVoidAsync( "Oqtane.Interop.uploadFiles", - posturl, folder, id, antiforgerytoken); + posturl, folder, id, antiforgerytoken, jwt); return Task.CompletedTask; } catch diff --git a/Oqtane.Maui/wwwroot/js/interop.js b/Oqtane.Maui/wwwroot/js/interop.js index a901c7be..8305f766 100644 --- a/Oqtane.Maui/wwwroot/js/interop.js +++ b/Oqtane.Maui/wwwroot/js/interop.js @@ -284,7 +284,7 @@ Oqtane.Interop = { } return files; }, - uploadFiles: function (posturl, folder, id, antiforgerytoken) { + uploadFiles: function (posturl, folder, id, antiforgerytoken, jwt) { var fileinput = document.getElementById('FileInput_' + id); var files = fileinput.files; var progressinfo = document.getElementById('ProgressInfo_' + id); @@ -323,6 +323,10 @@ Oqtane.Interop = { data.append('formfile', Chunk, FileName); var request = new XMLHttpRequest(); request.open('POST', posturl, true); + if (jwt !== "") { + request.setRequestHeader('Authorization', 'Bearer ' + jwt); + request.withCredentials = true; + } request.upload.onloadstart = function (e) { if (progressinfo !== null && progressbar !== null) { progressinfo.innerHTML = file.name + ' 0%'; diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index da191dcc..93126c03 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -131,6 +131,16 @@ namespace Oqtane .WithSiteIdentity() .WithSiteAuthentication(); + services.AddCors(options => + { + options.AddPolicy(Constants.MauiUserAgent, + policy => + { + policy.WithOrigins("https://0.0.0.0", "http://0.0.0.0", "app://0.0.0.0") + .AllowAnyHeader().AllowCredentials(); + }); + }); + services.AddMvc(options => { options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); @@ -176,6 +186,7 @@ namespace Oqtane app.UseHttpsRedirection(); app.UseStaticFiles(); + app.UseCors(Constants.MauiUserAgent); app.UseTenantResolution(); app.UseJwtAuthorization(); app.UseBlazorFrameworkFiles(); diff --git a/Oqtane.Server/wwwroot/js/interop.js b/Oqtane.Server/wwwroot/js/interop.js index a901c7be..8305f766 100644 --- a/Oqtane.Server/wwwroot/js/interop.js +++ b/Oqtane.Server/wwwroot/js/interop.js @@ -284,7 +284,7 @@ Oqtane.Interop = { } return files; }, - uploadFiles: function (posturl, folder, id, antiforgerytoken) { + uploadFiles: function (posturl, folder, id, antiforgerytoken, jwt) { var fileinput = document.getElementById('FileInput_' + id); var files = fileinput.files; var progressinfo = document.getElementById('ProgressInfo_' + id); @@ -323,6 +323,10 @@ Oqtane.Interop = { data.append('formfile', Chunk, FileName); var request = new XMLHttpRequest(); request.open('POST', posturl, true); + if (jwt !== "") { + request.setRequestHeader('Authorization', 'Bearer ' + jwt); + request.withCredentials = true; + } request.upload.onloadstart = function (e) { if (progressinfo !== null && progressbar !== null) { progressinfo.innerHTML = file.name + ' 0%'; diff --git a/Oqtane.Shared/Shared/Constants.cs b/Oqtane.Shared/Shared/Constants.cs index d0b44394..0e3d8e76 100644 --- a/Oqtane.Shared/Shared/Constants.cs +++ b/Oqtane.Shared/Shared/Constants.cs @@ -80,6 +80,7 @@ namespace Oqtane.Shared public static readonly string MauiUserAgent = "MAUI"; public static readonly string MauiAliasPath = "Alias-Path"; + public static readonly string VisitorCookiePrefix = "APP_VISITOR_"; // Obsolete constants