using GanjooRazor.Utils;
using GSpotifyProxy.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Newtonsoft.Json;
using RSecurityBackend.Models.Auth.Db;
using RSecurityBackend.Models.Auth.ViewModels;
using RSecurityBackend.Models.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace GanjooRazor.Areas.Admin.Pages
{
public class UsersModel : PageModel
{
///
/// Last Error
///
public string LastError { get; set; }
public PublicRAppUser[] Users { get; set; }
public PaginationMetadata Paging { get; set; }
public List PaginationLinks { get; set; } = new List();
public int PageNumber { get; set; } = 1;
public int PageSize { get; set; } = 15;
public string FilterByEmail { get; set; }
public string FilterByNickName { get; set; }
public async Task OnGetAsync(int pageNumber = 1, int pageSize = 15, string filterByEmail = null, string filterByNickName = null)
{
if (string.IsNullOrEmpty(Request.Cookies["Token"]))
return Redirect("/");
PageNumber = pageNumber < 1 ? 1 : pageNumber;
PageSize = pageSize;
FilterByEmail = filterByEmail;
FilterByNickName = filterByNickName;
using (HttpClient secureClient = new HttpClient(new GanjoorReloginHandler(Request, Response)))
{
if (await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response))
{
var url = $"{APIRoot.Url}/api/users?PageNumber={PageNumber}&PageSize={PageSize}";
if (!string.IsNullOrEmpty(FilterByEmail))
url += $"&filterByEmail={Uri.EscapeDataString(FilterByEmail)}";
if (!string.IsNullOrEmpty(FilterByNickName))
url += $"&filterByNickName={Uri.EscapeDataString(FilterByNickName)}";
var response = await secureClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
Users = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
if (response.Headers.TryGetValues("paging-headers", out var values))
{
Paging = JsonConvert.DeserializeObject(values.FirstOrDefault());
if (Paging != null)
{
PaginationLinks = BuildPaginationLinks(PageNumber, Paging.totalPages, PageSize, FilterByEmail, FilterByNickName);
}
}
}
else
{
LastError = await response.Content.ReadAsStringAsync();
}
}
else
{
LastError = "لطفاً از گنجور خارج و مجددا به آن وارد شوید.";
}
}
return Page();
}
///
/// Builds a compact pager: first/prev, a window of page numbers around the
/// current page (with first/last always included and "…" for gaps), next/last.
/// Avoids listing every single page number when there are many pages.
///
private static List BuildPaginationLinks(int currentPage, int totalPages, int pageSize, string filterByEmail, string filterByNickName)
{
var links = new List();
if (totalPages < 1)
return links;
string UrlFor(int p)
{
var u = $"?pageNumber={p}&pageSize={pageSize}";
if (!string.IsNullOrEmpty(filterByEmail))
u += $"&filterByEmail={Uri.EscapeDataString(filterByEmail)}";
if (!string.IsNullOrEmpty(filterByNickName))
u += $"&filterByNickName={Uri.EscapeDataString(filterByNickName)}";
return u;
}
// first / previous
links.Add(new NameIdUrlImage() { Name = "▶▶ اول", Url = currentPage <= 1 ? "" : UrlFor(1) });
links.Add(new NameIdUrlImage() { Name = "▶ قبلی", Url = currentPage <= 1 ? "" : UrlFor(currentPage - 1) });
// window of page numbers around current, always including page 1 and totalPages
const int windowRadius = 2;
var pagesToShow = new SortedSet();
for (int p = Math.Max(1, currentPage - windowRadius); p <= Math.Min(totalPages, currentPage + windowRadius); p++)
pagesToShow.Add(p);
pagesToShow.Add(1);
pagesToShow.Add(totalPages);
int? previousShown = null;
foreach (var p in pagesToShow)
{
if (previousShown.HasValue && p > previousShown.Value + 1)
{
links.Add(new NameIdUrlImage() { Name = "…", Url = "" });
}
links.Add(new NameIdUrlImage() { Name = p.ToString(), Url = p == currentPage ? "" : UrlFor(p) });
previousShown = p;
}
// next / last
links.Add(new NameIdUrlImage() { Name = "بعدی ◀", Url = currentPage >= totalPages ? "" : UrlFor(currentPage + 1) });
links.Add(new NameIdUrlImage() { Name = "آخر ◀◀", Url = currentPage >= totalPages ? "" : UrlFor(totalPages) });
return links;
}
///
/// role names for a specific user - ?handler=Roles&id=...
///
public async Task OnGetRolesAsync(Guid id)
{
using (HttpClient secureClient = new HttpClient(new GanjoorReloginHandler(Request, Response)))
{
if (!await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response))
return BadRequest("لطفاً از گنجور خارج و مجددا به آن وارد شوید.");
var response = await secureClient.GetAsync($"{APIRoot.Url}/api/users/{id}/roles");
if (!response.IsSuccessStatusCode)
return BadRequest(await response.Content.ReadAsStringAsync());
var roles = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
return new JsonResult(roles);
}
}
///
/// all defined role names, for populating the "add role" picker - ?handler=AllRoles
///
public async Task OnGetAllRolesAsync()
{
using (HttpClient secureClient = new HttpClient(new GanjoorReloginHandler(Request, Response)))
{
if (!await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response))
return BadRequest("لطفاً از گنجور خارج و مجددا به آن وارد شوید.");
var response = await secureClient.GetAsync($"{APIRoot.Url}/api/roles");
if (!response.IsSuccessStatusCode)
return BadRequest(await response.Content.ReadAsStringAsync());
var roles = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
return new JsonResult(roles.Select(r => r.Name).ToArray());
}
}
///
/// add a role to a user - ?handler=AddRole
///
public async Task OnPostAddRoleAsync(Guid id, string role)
{
using (HttpClient secureClient = new HttpClient(new GanjoorReloginHandler(Request, Response)))
{
if (!await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response))
return BadRequest("لطفاً از گنجور خارج و مجددا به آن وارد شوید.");
var response = await secureClient.PostAsync($"{APIRoot.Url}/api/users/{id}/roles/{Uri.EscapeDataString(role)}", null);
if (!response.IsSuccessStatusCode)
return BadRequest(await response.Content.ReadAsStringAsync());
return new JsonResult(true);
}
}
///
/// remove a role from a user - ?handler=Role (DELETE)
///
public async Task OnDeleteRoleAsync(Guid id, string role)
{
using (HttpClient secureClient = new HttpClient(new GanjoorReloginHandler(Request, Response)))
{
if (!await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response))
return BadRequest("لطفاً از گنجور خارج و مجددا به آن وارد شوید.");
var response = await secureClient.DeleteAsync($"{APIRoot.Url}/api/users/{id}/roles/{Uri.EscapeDataString(role)}");
if (!response.IsSuccessStatusCode)
return BadRequest(await response.Content.ReadAsStringAsync());
return new JsonResult(true);
}
}
///
/// toggle a user's active/inactive status - ?handler=ToggleStatus
///
public async Task OnPostToggleStatusAsync(Guid id, bool active)
{
using (HttpClient secureClient = new HttpClient(new GanjoorReloginHandler(Request, Response)))
{
if (!await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response))
return BadRequest("لطفاً از گنجور خارج و مجددا به آن وارد شوید.");
var userInfoResponse = await secureClient.GetAsync($"{APIRoot.Url}/api/users/{id}");
if (!userInfoResponse.IsSuccessStatusCode)
return BadRequest(await userInfoResponse.Content.ReadAsStringAsync());
var userInfo = JsonConvert.DeserializeObject(await userInfoResponse.Content.ReadAsStringAsync());
// ModifyUser rejects the request unless IsAdmin exactly matches the user's actual
// current admin-role membership (this endpoint cannot itself change admin status),
// so we need their real membership, not a guess.
var rolesResponse = await secureClient.GetAsync($"{APIRoot.Url}/api/users/{id}/roles");
if (!rolesResponse.IsSuccessStatusCode)
return BadRequest(await rolesResponse.Content.ReadAsStringAsync());
var currentRoles = JsonConvert.DeserializeObject(await rolesResponse.Content.ReadAsStringAsync());
bool isCurrentlyAdmin = currentRoles.Contains("Administrator");
var updateModel = new RegisterRAppUser()
{
Password = "",
IsAdmin = isCurrentlyAdmin,
Id = userInfo.Id,
Username = userInfo.Username,
Email = userInfo.Email,
PhoneNumber = userInfo.PhoneNumber,
FirstName = userInfo.FirstName,
SurName = userInfo.SurName,
Status = active ? RAppUserStatus.Active : RAppUserStatus.Inactive,
RImageId = userInfo.RImageId,
NickName = userInfo.NickName,
Bio = userInfo.Bio,
Website = userInfo.Website
};
var response = await secureClient.PutAsync($"{APIRoot.Url}/api/users/{id}", new StringContent(JsonConvert.SerializeObject(updateModel), Encoding.UTF8, "application/json"));
if (!response.IsSuccessStatusCode)
return BadRequest(await response.Content.ReadAsStringAsync());
return new JsonResult(true);
}
}
}
}