|
diff --git a/GanjooRazor/Pages/Auth/Login.cshtml.cs b/GanjooRazor/Pages/Auth/Login.cshtml.cs
index 93975c62..a5034d3b 100644
--- a/GanjooRazor/Pages/Auth/Login.cshtml.cs
+++ b/GanjooRazor/Pages/Auth/Login.cshtml.cs
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
+using System;
using System.Net.Http;
namespace GanjooRazor.Pages
@@ -15,6 +16,12 @@ namespace GanjooRazor.Pages
public string RedirectUrl { get; set; }
+ ///
+ /// , URL-encoded for embedding directly in the login form's
+ /// action attribute
+ ///
+ public string RedirectUrlEncoded => Uri.EscapeDataString(RedirectUrl);
+
public void OnGet()
{
UserFriendlyName = Request.Cookies["Name"];
diff --git a/GanjooRazor/Pages/Index.cshtml.cs b/GanjooRazor/Pages/Index.cshtml.cs
index 9114df57..5e4977fe 100644
--- a/GanjooRazor/Pages/Index.cshtml.cs
+++ b/GanjooRazor/Pages/Index.cshtml.cs
@@ -5,6 +5,7 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RMuseum.Models.Ganjoor.ViewModels;
using System.Collections.Generic;
+using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
@@ -139,11 +140,33 @@ namespace GanjooRazor.Pages
return Page();
}
+ // A fresh/forked install has an empty (or nearly empty) database: no poets, or no
+ // century grouping yet. The view below assumes at least the "popular poets" group
+ // (Id == 0) exists — PoetGroups.Where(g => g.Id == 0).Single() — and throws on an
+ // empty database instead of rendering something useful. Steer the visitor toward
+ // fixing that instead of letting them hit an unhandled exception: log in first if
+ // needed, then straight to the admin page that can seed real content.
+ if (IsDatabaseEffectivelyEmpty())
+ {
+ const string targetUrl = "/Admin/PublicDataImport";
+ return LoggedIn ? Redirect(targetUrl) : Redirect($"/login?redirect={targetUrl}");
+ }
+
ViewData["Title"] = "گنجور";
return Page();
}
+ ///
+ /// true if there's nothing meaningful to show on the home page yet — no poets at all, or
+ /// no century grouping (the "popular poets" group with Id == 0 that the view relies on).
+ ///
+ private bool IsDatabaseEffectivelyEmpty()
+ {
+ return Poets == null || Poets.Count == 0
+ || PoetGroups == null || !PoetGroups.Any(g => g.Id == 0);
+ }
+
public async Task OnGetPoetInformationAsync(int id)
{
if (id == 0)
diff --git a/GanjooRazor/Pages/LoginPartialEnabledPageModel.cs b/GanjooRazor/Pages/LoginPartialEnabledPageModel.cs
index 19b9eb41..3f274706 100644
--- a/GanjooRazor/Pages/LoginPartialEnabledPageModel.cs
+++ b/GanjooRazor/Pages/LoginPartialEnabledPageModel.cs
@@ -208,8 +208,27 @@ namespace GanjooRazor.Pages
}
Response.Cookies.Append("CanTranslate", canTranlate.ToString(), cookieOption);
+ return Redirect(GetSafeRedirectTarget());
+ }
- return Redirect(Request.Path);
+ ///
+ /// Resolves where to send the visitor after a successful login. Prefers the "redirect"
+ /// query string value (set by 's form action so a login triggered
+ /// from /login?redirect=X lands on X afterward) over the previous default of always using
+ /// Request.Path, which just bounced back to the login page itself when login was posted
+ /// from there. Only accepts a local, root-relative path ("/..." and not "//..." or a
+ /// scheme — those are how open-redirect payloads look) to avoid the visitor's own
+ /// "redirect" query value being used to send them somewhere else entirely; anything else
+ /// falls back to the old behavior.
+ ///
+ private string GetSafeRedirectTarget()
+ {
+ string redirect = Request.Query["redirect"];
+ if (!string.IsNullOrEmpty(redirect) && redirect.StartsWith("/") && !redirect.StartsWith("//"))
+ {
+ return redirect;
+ }
+ return Request.Path;
}
public Task OnGetCheckIfHasNotificationsAsync()
|