diff --git a/src/Ombi.Helpers/CacheKeys.cs b/src/Ombi.Helpers/CacheKeys.cs index 1bbdb66e4..1466d425e 100644 --- a/src/Ombi.Helpers/CacheKeys.cs +++ b/src/Ombi.Helpers/CacheKeys.cs @@ -7,5 +7,6 @@ namespace Ombi.Helpers public static class CacheKeys { public const string Update = nameof(Update); + public const string OmbiSettings = nameof(OmbiSettings); } } diff --git a/src/Ombi.Helpers/StringHelpers.cs b/src/Ombi.Helpers/StringHelpers.cs new file mode 100644 index 000000000..00b699581 --- /dev/null +++ b/src/Ombi.Helpers/StringHelpers.cs @@ -0,0 +1,34 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2017 Jamie Rees +// File: StringHelpers.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +namespace Ombi.Helpers +{ + public static class StringHelpers + { + public static bool IsNullOrEmpty(this string s) => string.IsNullOrEmpty(s); + public static bool HasValue(this string s) => !IsNullOrEmpty(s); + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/auth/auth.service.ts b/src/Ombi/ClientApp/app/auth/auth.service.ts index 89f38cf4c..e3cd6b1fb 100644 --- a/src/Ombi/ClientApp/app/auth/auth.service.ts +++ b/src/Ombi/ClientApp/app/auth/auth.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { Headers, Http } from "@angular/http"; import { JwtHelper, tokenNotExpired } from "angular2-jwt"; import { Observable } from "rxjs/Rx"; @@ -10,8 +11,8 @@ import { ILocalUser, IUserLogin } from "./IUserLogin"; export class AuthService extends ServiceHelpers { public jwtHelper: JwtHelper = new JwtHelper(); - constructor(http: Http) { - super(http, "/api/v1/token"); + constructor(http: Http, public platformLocation: PlatformLocation) { + super(http, "/api/v1/token", platformLocation); } public login(login: IUserLogin): Observable { diff --git a/src/Ombi/ClientApp/app/services/applications/emby.service.ts b/src/Ombi/ClientApp/app/services/applications/emby.service.ts index 70d4cf5c7..71788328b 100644 --- a/src/Ombi/ClientApp/app/services/applications/emby.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/emby.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { Http } from "@angular/http"; import { AuthHttp } from "angular2-jwt"; import { Observable } from "rxjs/Rx"; @@ -9,8 +10,8 @@ import { IEmbySettings, IUsersModel } from "../../interfaces"; @Injectable() export class EmbyService extends ServiceAuthHelpers { - constructor(http: AuthHttp, private regularHttp: Http) { - super(http, "/api/v1/Emby/"); + constructor(http: AuthHttp, private regularHttp: Http, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Emby/", platformLocation); } public logIn(settings: IEmbySettings): Observable { diff --git a/src/Ombi/ClientApp/app/services/applications/plex.service.ts b/src/Ombi/ClientApp/app/services/applications/plex.service.ts index ea4e89230..ff1743355 100644 --- a/src/Ombi/ClientApp/app/services/applications/plex.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/plex.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { Http } from "@angular/http"; import { AuthHttp } from "angular2-jwt"; @@ -10,8 +11,8 @@ import { IPlexAuthentication, IPlexLibResponse, IPlexServer, IPlexServerViewMode @Injectable() export class PlexService extends ServiceAuthHelpers { - constructor(http: AuthHttp, private regularHttp: Http) { - super(http, "/api/v1/Plex/"); + constructor(http: AuthHttp, private regularHttp: Http, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Plex/", platformLocation); } public logIn(login: string, password: string): Observable { diff --git a/src/Ombi/ClientApp/app/services/applications/radarr.service.ts b/src/Ombi/ClientApp/app/services/applications/radarr.service.ts index a5d5bc248..6b4baadc0 100644 --- a/src/Ombi/ClientApp/app/services/applications/radarr.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/radarr.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { AuthHttp } from "angular2-jwt"; import { Observable } from "rxjs/Rx"; @@ -8,8 +9,8 @@ import { ServiceAuthHelpers } from "../service.helpers"; @Injectable() export class RadarrService extends ServiceAuthHelpers { - constructor(http: AuthHttp) { - super(http, "/api/v1/Radarr"); + constructor(http: AuthHttp, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Radarr", platformLocation); } public getRootFolders(settings: IRadarrSettings): Observable { diff --git a/src/Ombi/ClientApp/app/services/applications/sonarr.service.ts b/src/Ombi/ClientApp/app/services/applications/sonarr.service.ts index 57a6e2440..2da534eb6 100644 --- a/src/Ombi/ClientApp/app/services/applications/sonarr.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/sonarr.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { AuthHttp } from "angular2-jwt"; import { Observable } from "rxjs/Rx"; @@ -8,8 +9,8 @@ import { ServiceAuthHelpers } from "../service.helpers"; @Injectable() export class SonarrService extends ServiceAuthHelpers { - constructor(http: AuthHttp) { - super(http, "/api/v1/Sonarr"); + constructor(http: AuthHttp, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Sonarr", platformLocation); } public getRootFolders(settings: ISonarrSettings): Observable { diff --git a/src/Ombi/ClientApp/app/services/applications/tester.service.ts b/src/Ombi/ClientApp/app/services/applications/tester.service.ts index ef38b4ecf..eb6109ab6 100644 --- a/src/Ombi/ClientApp/app/services/applications/tester.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/tester.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { AuthHttp } from "angular2-jwt"; import { Observable } from "rxjs/Rx"; @@ -19,8 +20,8 @@ import { @Injectable() export class TesterService extends ServiceAuthHelpers { - constructor(http: AuthHttp) { - super(http, "/api/v1/tester/"); + constructor(http: AuthHttp, public platformLocation: PlatformLocation) { + super(http, "/api/v1/tester/", platformLocation); } public discordTest(settings: IDiscordNotifcationSettings): Observable { diff --git a/src/Ombi/ClientApp/app/services/identity.service.ts b/src/Ombi/ClientApp/app/services/identity.service.ts index b8b4231ac..0e55d5e34 100644 --- a/src/Ombi/ClientApp/app/services/identity.service.ts +++ b/src/Ombi/ClientApp/app/services/identity.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { Http } from "@angular/http"; import { AuthHttp } from "angular2-jwt"; import { Observable } from "rxjs/Rx"; @@ -8,8 +9,8 @@ import { ServiceAuthHelpers } from "./service.helpers"; @Injectable() export class IdentityService extends ServiceAuthHelpers { - constructor(http: AuthHttp, private regularHttp: Http) { - super(http, "/api/v1/Identity/"); + constructor(http: AuthHttp, private regularHttp: Http, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Identity/", platformLocation); } public createWizardUser(username: string, password: string): Observable { return this.regularHttp.post(`${this.url}Wizard/`, JSON.stringify({ username, password }), { headers: this.headers }).map(this.extractData); diff --git a/src/Ombi/ClientApp/app/services/image.service.ts b/src/Ombi/ClientApp/app/services/image.service.ts index 7ffe3873e..3c94b769b 100644 --- a/src/Ombi/ClientApp/app/services/image.service.ts +++ b/src/Ombi/ClientApp/app/services/image.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { Http } from "@angular/http"; import { Observable } from "rxjs/Rx"; @@ -7,8 +8,8 @@ import { ServiceHelpers } from "./service.helpers"; @Injectable() export class ImageService extends ServiceHelpers { - constructor(public http: Http) { - super(http, "/api/v1/Images/"); + constructor(public http: Http, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Images/", platformLocation); } public getRandomBackground(): Observable { diff --git a/src/Ombi/ClientApp/app/services/job.service.ts b/src/Ombi/ClientApp/app/services/job.service.ts index acadb2e8d..b9ab6a5ad 100644 --- a/src/Ombi/ClientApp/app/services/job.service.ts +++ b/src/Ombi/ClientApp/app/services/job.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { AuthHttp } from "angular2-jwt"; import { Observable } from "rxjs/Rx"; @@ -6,8 +7,8 @@ import { ServiceAuthHelpers } from "./service.helpers"; @Injectable() export class JobService extends ServiceAuthHelpers { - constructor(http: AuthHttp) { - super(http, "/api/v1/Job/"); + constructor(http: AuthHttp, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Job/", platformLocation); } public forceUpdate(): Observable { return this.http.post(`${this.url}update/`, { headers: this.headers }).map(this.extractData); diff --git a/src/Ombi/ClientApp/app/services/landingpage.service.ts b/src/Ombi/ClientApp/app/services/landingpage.service.ts index c8a393e53..80bfe2a73 100644 --- a/src/Ombi/ClientApp/app/services/landingpage.service.ts +++ b/src/Ombi/ClientApp/app/services/landingpage.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { Http } from "@angular/http"; import { Observable } from "rxjs/Rx"; @@ -7,8 +8,8 @@ import { ServiceHelpers } from "./service.helpers"; @Injectable() export class LandingPageService extends ServiceHelpers { - constructor(public http: Http) { - super(http, "/api/v1/LandingPage/"); + constructor(public http: Http, public platformLocation: PlatformLocation) { + super(http, "/api/v1/LandingPage/", platformLocation); } public getServerStatus(): Observable { diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index adc24f2eb..020827eda 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { Http } from "@angular/http"; import { AuthHttp } from "angular2-jwt"; import { Observable } from "rxjs/Rx"; @@ -12,8 +13,8 @@ import { ServiceAuthHelpers } from "./service.helpers"; @Injectable() export class RequestService extends ServiceAuthHelpers { - constructor(http: AuthHttp, private basicHttp: Http) { - super(http, "/api/v1/Request/"); + constructor(http: AuthHttp, private basicHttp: Http, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Request/", platformLocation); } public requestMovie(movie: ISearchMovieResult): Observable { diff --git a/src/Ombi/ClientApp/app/services/search.service.ts b/src/Ombi/ClientApp/app/services/search.service.ts index 855ceebbb..9535f154e 100644 --- a/src/Ombi/ClientApp/app/services/search.service.ts +++ b/src/Ombi/ClientApp/app/services/search.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { AuthHttp } from "angular2-jwt"; import { Observable } from "rxjs/Rx"; @@ -9,8 +10,8 @@ import { ServiceAuthHelpers } from "./service.helpers"; @Injectable() export class SearchService extends ServiceAuthHelpers { - constructor(http: AuthHttp) { - super(http, "/api/v1/search"); + constructor(http: AuthHttp, public platformLocation: PlatformLocation) { + super(http, "/api/v1/search", platformLocation); } // Movies diff --git a/src/Ombi/ClientApp/app/services/service.helpers.ts b/src/Ombi/ClientApp/app/services/service.helpers.ts index 702b6db3c..12be4f67d 100644 --- a/src/Ombi/ClientApp/app/services/service.helpers.ts +++ b/src/Ombi/ClientApp/app/services/service.helpers.ts @@ -1,4 +1,5 @@ -import { Headers, Http, Response } from "@angular/http"; +import { PlatformLocation } from "@angular/common"; +import { Headers, Http, Response } from "@angular/http"; import "rxjs/add/observable/throw"; import { Observable } from "rxjs/Observable"; @@ -8,7 +9,10 @@ export class ServiceHelpers { protected headers: Headers; - constructor(protected http: Http, protected url: string) { + constructor(protected http: Http, protected url: string, protected platformLocation: PlatformLocation) { + if (this.url.length > 1) { + this.url = platformLocation.getBaseHrefFromDOM() + this.url; + } this.headers = new Headers(); this.headers.append("Content-Type", "application/json; charset=utf-8"); } @@ -32,7 +36,10 @@ export class ServiceAuthHelpers { protected headers: Headers; - constructor(protected http: AuthHttp, protected url: string) { + constructor(protected http: AuthHttp, protected url: string, protected platformLocation: PlatformLocation) { + if (this.url.length > 1) { + this.url = platformLocation.getBaseHrefFromDOM() + this.url; + } this.headers = new Headers(); this.headers.append("Content-Type", "application/json; charset=utf-8"); } diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index 98e929d09..4ea75681d 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -1,4 +1,5 @@ -import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; +import { Injectable } from "@angular/core"; import { Http } from "@angular/http"; import { AuthHttp } from "angular2-jwt"; import { Observable } from "rxjs/Rx"; @@ -27,8 +28,9 @@ import { ServiceAuthHelpers } from "./service.helpers"; @Injectable() export class SettingsService extends ServiceAuthHelpers { - constructor(public httpAuth: AuthHttp, private nonAuthHttp: Http) { - super(httpAuth, "/api/v1/Settings"); + constructor(public httpAuth: AuthHttp, private nonAuthHttp: Http, + public platformLocation: PlatformLocation) { + super(httpAuth, "/api/v1/Settings", platformLocation); } public about(): Observable { diff --git a/src/Ombi/ClientApp/app/services/status.service.ts b/src/Ombi/ClientApp/app/services/status.service.ts index ee4d80b29..bf63d5087 100644 --- a/src/Ombi/ClientApp/app/services/status.service.ts +++ b/src/Ombi/ClientApp/app/services/status.service.ts @@ -1,4 +1,5 @@ import { Injectable } from "@angular/core"; +import { PlatformLocation } from "@angular/common"; import { Http } from "@angular/http"; import { Observable } from "rxjs/Rx"; @@ -6,8 +7,8 @@ import { ServiceHelpers } from "./service.helpers"; @Injectable() export class StatusService extends ServiceHelpers { - constructor(http: Http) { - super(http, "/api/v1/status/"); + constructor(http: Http, public platformLocation: PlatformLocation) { + super(http, "/api/v1/status/", platformLocation); } public getWizardStatus(): Observable { return this.http.get(`${this.url}Wizard/`, { headers: this.headers }).map(this.extractData); diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 1853a5ff9..6bded6b44 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -3,46 +3,34 @@ using System.IO; using System.Linq; using System.Net; using System.Security.Principal; -using System.Text; -using System.Threading.Tasks; using AutoMapper; using AutoMapper.EquivalencyExpression; using Hangfire; using Hangfire.Console; using Hangfire.Dashboard; using Hangfire.MemoryStorage; -using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.SpaServices.Webpack; using Microsoft.AspNetCore.StaticFiles; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Microsoft.Extensions.PlatformAbstractions; -using Microsoft.IdentityModel.Tokens; -using Ombi.Config; using Ombi.Core.Authentication; -using Ombi.Core.Claims; using Ombi.Core.Settings; using Ombi.DependencyInjection; using Ombi.Helpers; using Ombi.Mapping; -using Ombi.Models.Identity; using Ombi.Schedule; using Ombi.Settings.Settings.Models; using Ombi.Store.Context; using Ombi.Store.Entities; using Serilog; using Serilog.Events; -using Swashbuckle.AspNetCore.Swagger; namespace Ombi { @@ -157,15 +145,23 @@ namespace Ombi }); // Setup the scheduler - var jobSetup = (IJobSetup)app.ApplicationServices.GetService(typeof(IJobSetup)); + var jobSetup = app.ApplicationServices.GetService(); jobSetup.Setup(); ctx.Seed(); var provider = new FileExtensionContentTypeProvider { Mappings = { [".map"] = "application/octet-stream" } }; + var ombiService = + app.ApplicationServices.GetService>(); + var settings = ombiService.GetSettings(); + if (settings.BaseUrl.HasValue()) + { + app.UsePathBase(settings.BaseUrl); + } + app.UseStaticFiles(new StaticFileOptions() { - ContentTypeProvider = provider + ContentTypeProvider = provider, }); app.UseAuthentication(); diff --git a/src/Ombi/TagHelpers/ReverseProxyTagHelper.cs b/src/Ombi/TagHelpers/ReverseProxyTagHelper.cs deleted file mode 100644 index 684fd036e..000000000 --- a/src/Ombi/TagHelpers/ReverseProxyTagHelper.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.AspNetCore.Razor.TagHelpers; -using Ombi.Core.Settings; -using Ombi.Settings.Settings.Models; - -namespace Ombi.TagHelpers -{ - public class ReverseProxyTagHelper : TagHelper - { - public ReverseProxyTagHelper(ISettingsService c) - { - _ctx = c; - } - - private readonly ISettingsService _ctx; - - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "base"; - var s = _ctx.GetSettings(); - var baseUrl = string.IsNullOrEmpty(s.BaseUrl) ? "/" : s.BaseUrl; - output.Attributes.SetAttribute("href", baseUrl); - } - } -} diff --git a/src/Ombi/Views/Shared/_Layout.cshtml b/src/Ombi/Views/Shared/_Layout.cshtml index 14dcf0cdb..e62cc43c9 100644 --- a/src/Ombi/Views/Shared/_Layout.cshtml +++ b/src/Ombi/Views/Shared/_Layout.cshtml @@ -1,10 +1,26 @@ - +@using Ombi.Core.Settings +@using Ombi.Settings.Settings.Models +@inject ISettingsService Settings +@{ + var s = await Settings.GetSettingsAsync(); + var baseUrl = s.BaseUrl; + + if (!baseUrl.EndsWith("/")) + { + baseUrl = baseUrl.TrimEnd('/'); + } + if (baseUrl.StartsWith("/")) + { + baseUrl = baseUrl.TrimStart('/'); + } +} + Ombi - +