diff --git a/src/Ombi.Helpers/StartupSingleton.cs b/src/Ombi.Helpers/StartupSingleton.cs new file mode 100644 index 000000000..41fd1a9ab --- /dev/null +++ b/src/Ombi.Helpers/StartupSingleton.cs @@ -0,0 +1,15 @@ +namespace Ombi.Helpers +{ + public class StartupSingleton + { + private static StartupSingleton instance; + + private StartupSingleton() { } + + public static StartupSingleton Instance => instance ?? (instance = new StartupSingleton()); + + public string StoragePath { get; set; } + + public string SecurityKey { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Helpers/StoragePathSingleton.cs b/src/Ombi.Helpers/StoragePathSingleton.cs deleted file mode 100644 index c502c4a54..000000000 --- a/src/Ombi.Helpers/StoragePathSingleton.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Ombi.Helpers -{ - public class StoragePathSingleton - { - private static StoragePathSingleton instance; - - private StoragePathSingleton() { } - - public static StoragePathSingleton Instance => instance ?? (instance = new StoragePathSingleton()); - - public string StoragePath { get; set; } - } -} \ No newline at end of file diff --git a/src/Ombi.Store/Entities/ApplicationConfiguration.cs b/src/Ombi.Store/Entities/ApplicationConfiguration.cs index 809264312..012a80345 100644 --- a/src/Ombi.Store/Entities/ApplicationConfiguration.cs +++ b/src/Ombi.Store/Entities/ApplicationConfiguration.cs @@ -17,6 +17,7 @@ namespace Ombi.Store.Entities TheMovieDb = 4, StoragePath = 5, Notification = 6, - BaseUrl=7, + BaseUrl = 7, + SecurityToken = 8 } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/package.json b/src/Ombi/ClientApp/package.json index f3d62fbc0..0b3cc9e9b 100644 --- a/src/Ombi/ClientApp/package.json +++ b/src/Ombi/ClientApp/package.json @@ -36,7 +36,7 @@ "angular-router-loader": "^0.8.5", "angularx-qrcode": "^2.1.0", "bootstrap": "^4.2.1", - "chart.js": "2.5.0", + "chart.js": "2.9.4", "core-js": "^2.5.4", "eventemitter2": "^5.0.1", "font-awesome": "^4.7.0", diff --git a/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.html b/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.html index 25a120304..f105b23ab 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.html @@ -1,13 +1,13 @@
-
+
dashboard calendar_view_day
-
+
-
\ No newline at end of file +
diff --git a/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.scss b/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.scss index df7db5335..c2386ae8f 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.scss +++ b/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.scss @@ -26,6 +26,13 @@ padding-top: 1%; } +.discover-layout { + position: absolute; + float: right; + margin-right: 36px; + z-index: 1; +} + ::ng-deep .mat-card-image { height: 75%; object-fit: cover; @@ -195,4 +202,9 @@ max-width: 11.111111%; min-width: 11.111111%; } +} +@media (max-width: 420px) { + .discover-layout{ + display: none; + } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/services/system.service.ts b/src/Ombi/ClientApp/src/app/services/system.service.ts index 20f60c8d8..ef6f947a8 100644 --- a/src/Ombi/ClientApp/src/app/services/system.service.ts +++ b/src/Ombi/ClientApp/src/app/services/system.service.ts @@ -18,4 +18,7 @@ export class SystemService extends ServiceHelpers { public getLog(logName: string): Observable { return this.http.get(`${this.url}logs/${logName}`, {responseType: 'text'}); } + public getNews(): Observable { + return this.http.get(`${this.url}news`, {responseType: 'text'}); + } } diff --git a/src/Ombi/ClientApp/src/app/settings/about/about.component.html b/src/Ombi/ClientApp/src/app/settings/about/about.component.html index b52d00c43..a9e1028d1 100644 --- a/src/Ombi/ClientApp/src/app/settings/about/about.component.html +++ b/src/Ombi/ClientApp/src/app/settings/about/about.component.html @@ -1,7 +1,8 @@ 
About - +
+
NOT SUPPORTED OS. Please use the docker image available on the Container Station (It's free)
@@ -91,6 +92,11 @@
- +
+
+
+

News

+
+
diff --git a/src/Ombi/ClientApp/src/app/settings/about/about.component.scss b/src/Ombi/ClientApp/src/app/settings/about/about.component.scss index 5afb20333..daeccd03a 100644 --- a/src/Ombi/ClientApp/src/app/settings/about/about.component.scss +++ b/src/Ombi/ClientApp/src/app/settings/about/about.component.scss @@ -23,4 +23,18 @@ margin: auto; width: 85%; margin-top:10px; + } + + :host ::ng-deep strong { + color: #fff; + background-color: #007bff; + display: inline-block; + padding: 0.25em 0.4em; + font-size: 75%; + font-weight: 700; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25rem; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/about/about.component.ts b/src/Ombi/ClientApp/src/app/settings/about/about.component.ts index f1ea6c29d..c3fd4b056 100644 --- a/src/Ombi/ClientApp/src/app/settings/about/about.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/about/about.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from "@angular/core"; import { IAbout } from "../../interfaces/ISettings"; -import { JobService, SettingsService, HubService } from "../../services"; +import { JobService, SettingsService, HubService, SystemService } from "../../services"; import { IConnectedUser } from "../../interfaces"; @Component({ @@ -12,14 +12,16 @@ export class AboutComponent implements OnInit { public about: IAbout; public newUpdate: boolean; public connectedUsers: IConnectedUser[]; + public newsHtml: string; constructor(private readonly settingsService: SettingsService, - private readonly jobService: JobService, - private readonly hubService: HubService) { } + private readonly jobService: JobService, + private readonly hubService: HubService, + private readonly systemService: SystemService) { } public async ngOnInit() { this.settingsService.about().subscribe(x => this.about = x); - + this.newsHtml = await this.systemService.getNews().toPromise(); // TODO // this.jobService.getCachedUpdate().subscribe(x => { diff --git a/src/Ombi/ClientApp/src/styles/shared.scss b/src/Ombi/ClientApp/src/styles/shared.scss index 655ac22f0..c743d06a9 100644 --- a/src/Ombi/ClientApp/src/styles/shared.scss +++ b/src/Ombi/ClientApp/src/styles/shared.scss @@ -38,7 +38,7 @@ html, body { min-height: 100vh; - overflow: auto; + overflow: initial; scrollbar-color: #616161 #303030; //firefox scrollbar-width: thin; //firefox -webkit-overflow-scrolling: touch; @@ -138,4 +138,4 @@ table { ::ng-deep .mat-form-field.mat-focused .mat-form-field-label { color: $accent; -} \ No newline at end of file +} diff --git a/src/Ombi/ClientApp/yarn.lock b/src/Ombi/ClientApp/yarn.lock index 09499f2cb..68a8a794f 100644 --- a/src/Ombi/ClientApp/yarn.lock +++ b/src/Ombi/ClientApp/yarn.lock @@ -2331,25 +2331,28 @@ chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" -chart.js@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.5.0.tgz#fe6e751a893769f56e72bee5ad91207e1c592957" +chart.js@2.9.4: + version "2.9.4" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.4.tgz#0827f9563faffb2dc5c06562f8eb10337d5b9684" + integrity sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A== dependencies: - chartjs-color "^2.0.0" - moment "^2.10.6" + chartjs-color "^2.1.0" + moment "^2.10.2" -chartjs-color-string@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz#8d3752d8581d86687c35bfe2cb80ac5213ceb8c1" +chartjs-color-string@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71" + integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A== dependencies: color-name "^1.0.0" -chartjs-color@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.2.0.tgz#84a2fb755787ed85c39dd6dd8c7b1d88429baeae" +chartjs-color@^2.1.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0" + integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w== dependencies: - chartjs-color-string "^0.5.0" - color-convert "^0.5.3" + chartjs-color-string "^0.6.0" + color-convert "^1.9.3" "chokidar@>=2.0.0 <4.0.0": version "3.3.1" @@ -2582,11 +2585,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd" - -color-convert@^1.9.0, color-convert@^1.9.1: +color-convert@^1.9.0, color-convert@^1.9.1, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" dependencies: @@ -5661,10 +5660,15 @@ moment-timezone@^0.5.23: dependencies: moment ">= 2.9.0" -"moment@>= 2.9.0", moment@^2.10.6, moment@^2.23.0: +"moment@>= 2.9.0", moment@^2.23.0: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" +moment@^2.10.2: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" diff --git a/src/Ombi/Controllers/V1/SettingsController.cs b/src/Ombi/Controllers/V1/SettingsController.cs index 32cafd904..8cef872f4 100644 --- a/src/Ombi/Controllers/V1/SettingsController.cs +++ b/src/Ombi/Controllers/V1/SettingsController.cs @@ -117,7 +117,7 @@ namespace Ombi.Controllers.V1 public AboutViewModel About() { var dbConfiguration = DatabaseExtensions.GetDatabaseConfiguration(); - var storage = StoragePathSingleton.Instance; + var storage = StartupSingleton.Instance; var model = new AboutViewModel { FrameworkDescription = RuntimeInformation.FrameworkDescription, diff --git a/src/Ombi/Controllers/V1/TokenController.cs b/src/Ombi/Controllers/V1/TokenController.cs index 80aa96f85..e133a939d 100644 --- a/src/Ombi/Controllers/V1/TokenController.cs +++ b/src/Ombi/Controllers/V1/TokenController.cs @@ -136,7 +136,7 @@ namespace Ombi.Controllers.V1 }; claims.AddRange(roles.Select(role => new Claim("role", role))); - var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenAuthenticationOptions.SecretKey)); + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(StartupSingleton.Instance.SecurityKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); diff --git a/src/Ombi/Controllers/V2/SystemController.cs b/src/Ombi/Controllers/V2/SystemController.cs index 924532eda..d172eb37a 100644 --- a/src/Ombi/Controllers/V2/SystemController.cs +++ b/src/Ombi/Controllers/V2/SystemController.cs @@ -1,7 +1,9 @@ using System.IO; using System.Linq; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Markdig; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Ombi.Attributes; @@ -12,16 +14,27 @@ namespace Ombi.Controllers.V2 public class SystemController : V2Controller { private readonly IWebHostEnvironment _hosting; + private readonly HttpClient _client; - public SystemController(IWebHostEnvironment hosting) + public SystemController(IWebHostEnvironment hosting, IHttpClientFactory httpClientFactory) { _hosting = hosting; + _client = httpClientFactory.CreateClient(); + } + + [HttpGet("news")] + public async Task GetNews() + { + var result = await _client.GetAsync("https://raw.githubusercontent.com/tidusjar/Ombi.News/main/README.md"); + var content = await result.Content.ReadAsStringAsync(); + var md = Markdown.ToHtml(content); + return Ok(md); } [HttpGet("logs")] public IActionResult GetLogFiles() { - var logsFolder = Path.Combine(_hosting.ContentRootPath, "Logs"); + var logsFolder = Path.Combine(string.IsNullOrEmpty(Ombi.Helpers.StartupSingleton.Instance.StoragePath) ? _hosting.ContentRootPath : Helpers.StartupSingleton.Instance.StoragePath, "Logs"); var files = Directory .EnumerateFiles(logsFolder, "*.txt", SearchOption.TopDirectoryOnly) .Select(Path.GetFileName) @@ -33,7 +46,7 @@ namespace Ombi.Controllers.V2 [HttpGet("logs/{logFileName}")] public async Task ReadLogFile(string logFileName, CancellationToken token) { - var logFile = Path.Combine(_hosting.ContentRootPath, "Logs", logFileName); + var logFile = Path.Combine(string.IsNullOrEmpty(Ombi.Helpers.StartupSingleton.Instance.StoragePath) ? _hosting.ContentRootPath : Helpers.StartupSingleton.Instance.StoragePath, "Logs", logFileName); using (var fs = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (StreamReader reader = new StreamReader(fs)) { @@ -44,7 +57,7 @@ namespace Ombi.Controllers.V2 [HttpGet("logs/download/{logFileName}")] public IActionResult Download(string logFileName, CancellationToken token) { - var logFile = Path.Combine(_hosting.ContentRootPath, "Logs", logFileName); + var logFile = Path.Combine(string.IsNullOrEmpty(Ombi.Helpers.StartupSingleton.Instance.StoragePath) ? _hosting.ContentRootPath : Helpers.StartupSingleton.Instance.StoragePath, "Logs", logFileName); using (var fs = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (StreamReader reader = new StreamReader(fs)) { diff --git a/src/Ombi/Extensions/DatabaseExtensions.cs b/src/Ombi/Extensions/DatabaseExtensions.cs index 979f1688b..4d82031ef 100644 --- a/src/Ombi/Extensions/DatabaseExtensions.cs +++ b/src/Ombi/Extensions/DatabaseExtensions.cs @@ -62,7 +62,7 @@ namespace Ombi.Extensions public static DatabaseConfiguration GetDatabaseConfiguration() { - var i = StoragePathSingleton.Instance; + var i = StartupSingleton.Instance; if (string.IsNullOrEmpty(i.StoragePath)) { i.StoragePath = string.Empty; diff --git a/src/Ombi/Extensions/StartupExtensions.cs b/src/Ombi/Extensions/StartupExtensions.cs index b9d6ed320..cc90155e7 100644 --- a/src/Ombi/Extensions/StartupExtensions.cs +++ b/src/Ombi/Extensions/StartupExtensions.cs @@ -83,7 +83,7 @@ namespace Ombi var tokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.GetValue("SecretKey", string.Empty))), + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(StartupSingleton.Instance.SecurityKey)), RequireExpirationTime = true, ValidateLifetime = true, diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 49ed32d85..30ed06f01 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -18,7 +18,7 @@ using Ombi.Store.Context.Sqlite; namespace Ombi { - public class Program + public static class Program { private static string UrlArgs { get; set; } @@ -50,13 +50,11 @@ namespace Ombi UrlArgs = host; var urlValue = string.Empty; - var instance = StoragePathSingleton.Instance; + var instance = StartupSingleton.Instance; var demoInstance = DemoSingleton.Instance; demoInstance.Demo = demo; instance.StoragePath = storagePath ?? string.Empty; - // Check if we need to migrate the settings - DeleteSchedules(); - //CheckAndMigrate(); + var services = new ServiceCollection(); services.ConfigureDatabases(null); @@ -67,6 +65,8 @@ namespace Ombi var config = settingsDb.ApplicationConfigurations.ToList(); var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); var dbBaseUrl = config.FirstOrDefault(x => x.Type == ConfigurationTypes.BaseUrl); + var securityToken = config.FirstOrDefault(x => x.Type == ConfigurationTypes.SecurityToken); + CheckSecurityToken(securityToken, settingsDb, instance); if (url == null) { url = new ApplicationConfiguration @@ -136,18 +136,25 @@ namespace Ombi } } - private static void DeleteSchedules() + private static void CheckSecurityToken(ApplicationConfiguration securityToken, SettingsContext ctx, StartupSingleton instance) { - try + if (securityToken == null || string.IsNullOrEmpty(securityToken.Value)) { - if (File.Exists("Schedules.db")) + securityToken = new ApplicationConfiguration + { + Type = ConfigurationTypes.SecurityToken, + Value = Guid.NewGuid().ToString("N") + }; + + using (var tran = ctx.Database.BeginTransaction()) { - File.Delete("Schedules.db"); + ctx.ApplicationConfigurations.Add(securityToken); + ctx.SaveChanges(); + tran.Commit(); } } - catch (Exception) - { - } + + instance.SecurityKey = securityToken.Value; } public static IHostBuilder CreateHostBuilder(string[] args) => diff --git a/src/Ombi/Properties/launchSettings.json b/src/Ombi/Properties/launchSettings.json index b62c1fba9..ab355f92a 100644 --- a/src/Ombi/Properties/launchSettings.json +++ b/src/Ombi/Properties/launchSettings.json @@ -22,7 +22,7 @@ }, "Ombi": { "commandName": "Project", - "commandLineArgs": "--host http://localhost:3577 --baseurl /ombi", + "commandLineArgs": "--host http://localhost:3577 ", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 29604520f..49227a344 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -35,7 +35,7 @@ namespace Ombi { public class Startup { - public static StoragePathSingleton StoragePath => StoragePathSingleton.Instance; + public static StartupSingleton StoragePath => StartupSingleton.Instance; public Startup(IWebHostEnvironment env) { @@ -84,6 +84,7 @@ namespace Ombi // setup.AddHealthCheckEndpoint("Ombi", "/health"); //}); services.AddMemoryCache(); + services.AddHttpClient(); services.AddJwtAuthentication(Configuration); @@ -164,7 +165,7 @@ namespace Ombi var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl); if (baseUrl != null) { - if (baseUrl.Value.HasValue() && settings.BaseUrl != baseUrl.Value) + if (baseUrl.Value.HasValue()) { settings.BaseUrl = baseUrl.Value; ombiService.SaveSettings(settings); diff --git a/src/Ombi/databasej.json b/src/Ombi/databasej.json new file mode 100644 index 000000000..7c77dd61a --- /dev/null +++ b/src/Ombi/databasej.json @@ -0,0 +1,14 @@ +{ + "OmbiDatabase": { + "Type": "MySQL", + "ConnectionString": "Server=192.168.68.118;Database=app.ombi.io;User=ombi" + }, + "SettingsDatabase": { + "Type": "MySQL", + "ConnectionString": "Server=192.168.68.118;Database=app.ombi.io;User=ombi" + }, + "ExternalDatabase": { + "Type": "MySQL", + "ConnectionString": "Server=192.168.68.118;Database=app.ombi.io;User=ombi" + } + } \ No newline at end of file