#498 import public data

This commit is contained in:
Hamid Reza Mohammadi 2026-08-14 16:20:36 +03:30
parent 839421ae73
commit 011e047619
4 changed files with 51 additions and 2 deletions

View File

@ -44,7 +44,7 @@
}
else
{
<form method="post" action="?handler=Login">
<form method="post" action="@("?handler=Login&redirect=" + Model.RedirectUrlEncoded)">
<table>
<tr>
<td>

View File

@ -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; }
/// <summary>
/// <see cref="RedirectUrl"/>, URL-encoded for embedding directly in the login form's
/// action attribute
/// </summary>
public string RedirectUrlEncoded => Uri.EscapeDataString(RedirectUrl);
public void OnGet()
{
UserFriendlyName = Request.Cookies["Name"];

View File

@ -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();
}
/// <summary>
/// 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).
/// </summary>
private bool IsDatabaseEffectivelyEmpty()
{
return Poets == null || Poets.Count == 0
|| PoetGroups == null || !PoetGroups.Any(g => g.Id == 0);
}
public async Task<IActionResult> OnGetPoetInformationAsync(int id)
{
if (id == 0)

View File

@ -208,8 +208,27 @@ namespace GanjooRazor.Pages
}
Response.Cookies.Append("CanTranslate", canTranlate.ToString(), cookieOption);
return Redirect(GetSafeRedirectTarget());
}
return Redirect(Request.Path);
/// <summary>
/// Resolves where to send the visitor after a successful login. Prefers the "redirect"
/// query string value (set by <see cref="LoginModel"/>'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.
/// </summary>
private string GetSafeRedirectTarget()
{
string redirect = Request.Query["redirect"];
if (!string.IsNullOrEmpty(redirect) && redirect.StartsWith("/") && !redirect.StartsWith("//"))
{
return redirect;
}
return Request.Path;
}
public Task<IActionResult> OnGetCheckIfHasNotificationsAsync()