Moved BaseUrl from appsettings.json to Database and fixed an issue in UI for setting base url based on a hack, rather than asking backend for it. (#644)

This commit is contained in:
Joseph Milazzo 2021-10-06 11:03:14 -07:00 committed by GitHub
parent e8e838d125
commit 977e364d5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 52 additions and 26 deletions

View File

@ -33,6 +33,14 @@ namespace API.Controllers
_accountService = accountService;
}
[AllowAnonymous]
[HttpGet("base-url")]
public async Task<ActionResult<string>> GetBaseUrl()
{
var settingsDto = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync();
return Ok(settingsDto.BaseUrl);
}
[Authorize(Policy = "RequireAdminRole")]
[HttpGet]
public async Task<ActionResult<ServerSettingDto>> GetSettings()
@ -91,8 +99,6 @@ namespace API.Controllers
? $"/{updateSettingsDto.BaseUrl}"
: updateSettingsDto.BaseUrl;
setting.Value = path;
// BaseUrl is managed in appSetting.json
Configuration.BaseUrl = updateSettingsDto.BaseUrl;
_unitOfWork.SettingsRepository.Update(setting);
}

View File

@ -27,8 +27,8 @@
/// </summary>
public bool EnableAuthentication { get; set; }
/// <summary>
/// Base Url for the kavita. Defaults to "/". Managed in appsettings.json.Requires restart to take effect.
/// Base Url for the kavita. Requires restart to take effect.
/// </summary>
public string BaseUrl { get; set; } = "/";
public string BaseUrl { get; set; }
}
}

View File

@ -35,6 +35,15 @@ namespace API.Data.Repositories
return _mapper.Map<ServerSettingDto>(settings);
}
public ServerSettingDto GetSettingsDto()
{
var settings = _context.ServerSetting
.Select(x => x)
.AsNoTracking()
.ToList();
return _mapper.Map<ServerSettingDto>(settings);
}
public Task<ServerSetting> GetSettingAsync(ServerSettingKey key)
{
return _context.ServerSetting.SingleOrDefaultAsync(x => x.Key == key);

View File

@ -50,7 +50,7 @@ namespace API.Data
new () {Key = ServerSettingKey.AllowStatCollection, Value = "true"},
new () {Key = ServerSettingKey.EnableOpds, Value = "false"},
new () {Key = ServerSettingKey.EnableAuthentication, Value = "true"},
new () {Key = ServerSettingKey.BaseUrl, Value = ""},// Not used from DB, but DB is sync with appSettings.json
new () {Key = ServerSettingKey.BaseUrl, Value = "/"},
};
foreach (var defaultSetting in defaultSettings)
@ -64,20 +64,11 @@ namespace API.Data
await context.SaveChangesAsync();
if (string.IsNullOrEmpty(Configuration.BaseUrl))
{
Configuration.BaseUrl = "/";
}
// Port and LoggingLevel are managed in appSettings.json. Update the DB values to match
context.ServerSetting.First(s => s.Key == ServerSettingKey.Port).Value =
Configuration.Port + string.Empty;
context.ServerSetting.First(s => s.Key == ServerSettingKey.LoggingLevel).Value =
Configuration.LogLevel + string.Empty;
context.ServerSetting.First(s => s.Key == ServerSettingKey.BaseUrl).Value =
Configuration.BaseUrl;
await context.SaveChangesAsync();

View File

@ -10,6 +10,7 @@ namespace API.Interfaces.Repositories
{
void Update(ServerSetting settings);
Task<ServerSettingDto> GetSettingsDtoAsync();
ServerSettingDto GetSettingsDto();
Task<ServerSetting> GetSettingAsync(ServerSettingKey key);
Task<IEnumerable<ServerSetting>> GetSettingsAsync();

View File

@ -5,6 +5,8 @@ using System.Linq;
using System.Net;
using System.Net.Sockets;
using API.Extensions;
using API.Interfaces;
using API.Interfaces.Repositories;
using API.Middleware;
using API.Services;
using API.Services.HostedServices;
@ -121,7 +123,7 @@ namespace API
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IBackgroundJobClient backgroundJobs, IWebHostEnvironment env,
IHostApplicationLifetime applicationLifetime)
IHostApplicationLifetime applicationLifetime, IServiceProvider serviceProvider)
{
app.UseMiddleware<ExceptionMiddleware>();
@ -160,7 +162,9 @@ namespace API
app.UseDefaultFiles();
if (!string.IsNullOrEmpty(Configuration.BaseUrl))
var service = serviceProvider.GetRequiredService<IUnitOfWork>();
var settings = service.SettingsRepository.GetSettingsDto();
if (!string.IsNullOrEmpty(settings.BaseUrl) && !settings.BaseUrl.Equals("/"))
{
var path = !Configuration.BaseUrl.StartsWith("/")
? $"/{Configuration.BaseUrl}"

View File

@ -0,0 +1,10 @@
/**
* This is for base url only. Not to be used my applicaiton, only loading and bootstrapping app
*/
export class ConfigData {
baseUrl: string = '/';
constructor(baseUrl: string) {
this.baseUrl = baseUrl;
}
}

View File

@ -31,6 +31,8 @@ import { CardsModule } from './cards/cards.module';
import { CollectionsModule } from './collections/collections.module';
import { ReadingListModule } from './reading-list/reading-list.module';
import { SAVER, getSaver } from './shared/_providers/saver.provider';
import { ConfigData } from './_models/config-data';
@NgModule({
declarations: [
@ -83,7 +85,7 @@ import { SAVER, getSaver } from './shared/_providers/saver.provider';
{provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true},
Title,
{provide: SAVER, useFactory: getSaver},
{ provide: APP_BASE_HREF, useValue: window['_app_base' as keyof Window] || '/' },
{ provide: APP_BASE_HREF, useFactory: (config: ConfigData) => config.baseUrl, deps: [ConfigData] },
],
entryComponents: [],
bootstrap: [AppComponent]

View File

@ -40,9 +40,4 @@
<app-root></app-root>
<noscript>Please enable JavaScript to continue using this application.</noscript>
</body>
<script>
(function() {
window['_app_base'] = '/' + window.location.pathname.split('/')[1];
})();
</script>
</html>

View File

@ -2,13 +2,21 @@ import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { ConfigData } from './app/_models/config-data';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
function fetchConfig(): Promise<ConfigData> {
return fetch(environment.apiUrl + 'settings/base-url')
.then(response => response.text())
.then(response => new ConfigData(response));
}
fetchConfig().then(config => {
platformBrowserDynamic([ { provide: ConfigData, useValue: config } ])
.bootstrapModule(AppModule)
.catch(err => console.error(err));
});