Files
SkyArtShop/Controllers/AdminController.cs
Local Server 703ab57984 Fix admin route access and backend configuration
- Added /admin redirect to login page in nginx config
- Fixed backend server.js route ordering for proper admin handling
- Updated authentication middleware and routes
- Added user management routes
- Configured PostgreSQL integration
- Updated environment configuration
2025-12-13 22:34:11 -06:00

204 lines
6.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SkyArtShop.Models;
using SkyArtShop.Services;
namespace SkyArtShop.Controllers;
[Route("admin")]
[Authorize(Roles = "Admin,MasterAdmin,Cashier,Accountant")]
public class AdminController : Controller
{
private readonly PostgreSQLService _pgService;
private readonly PostgreAuthService _pgAuthService;
public AdminController(PostgreSQLService pgService, PostgreAuthService pgAuthService)
{
_pgService = pgService;
_pgAuthService = pgAuthService;
}
[HttpGet("login")]
[AllowAnonymous]
public IActionResult Login()
{
IIdentity? identity = base.User.Identity;
if (identity != null && identity.IsAuthenticated)
{
return RedirectToAction("Dashboard");
}
return View();
}
[HttpPost("login")]
[AllowAnonymous]
public async Task<IActionResult> Login(string email, string password)
{
AdminUser adminUser = await _pgAuthService.AuthenticateAsync(email, password);
if (adminUser == null)
{
base.ViewBag.Error = "Invalid email or password";
return View();
}
ClaimsPrincipal principal = _pgAuthService.CreateClaimsPrincipal(adminUser);
await base.HttpContext.SignInAsync("Cookies", principal, new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.AddDays(30.0)
});
return RedirectToAction("Dashboard");
}
[HttpGet("logout")]
public async Task<IActionResult> Logout()
{
await base.HttpContext.SignOutAsync("Cookies");
return RedirectToAction("Login");
}
[HttpGet("dashboard")]
public async Task<IActionResult> Dashboard()
{
List<Product> products = await _pgService.GetAllAsync<Product>("Products");
List<PortfolioProject> projects = await _pgService.GetAllAsync<PortfolioProject>("PortfolioProjects");
List<BlogPost> blogPosts = await _pgService.GetAllAsync<BlogPost>("BlogPosts");
List<Page> pages = await _pgService.GetAllAsync<Page>("Pages");
SiteSettings siteSettings = await _pgService.GetSiteSettingsAsync();
base.ViewBag.ProductCount = products.Count;
base.ViewBag.ProjectCount = projects.Count;
base.ViewBag.BlogCount = blogPosts.Count;
base.ViewBag.PageCount = pages.Count;
base.ViewBag.SiteName = siteSettings?.SiteName ?? "Sky Art Shop";
base.ViewBag.AdminEmail = base.User.Identity?.Name;
return View();
}
[HttpGet("")]
public IActionResult Index()
{
return RedirectToAction("Dashboard");
}
[HttpGet("system-status")]
[Authorize]
public async Task<IActionResult> SystemStatus()
{
try
{
var value = new
{
databaseConnected = true,
dbType = "PostgreSQL",
dbHost = "localhost",
dbName = "skyartshop",
dbVersion = "16",
userCount = (await _pgService.GetAllAsync<AdminUser>("AdminUsers")).Count,
timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss UTC")
};
return new JsonResult(value);
}
catch (Exception ex)
{
var value2 = new
{
databaseConnected = false,
error = ex.Message,
timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss UTC")
};
return new JsonResult(value2);
}
}
[HttpGet("change-password")]
public IActionResult ChangePassword()
{
return View();
}
[HttpGet("diagnostic")]
public IActionResult DiagnosticTest()
{
return View();
}
[HttpGet("reset-password-emergency")]
[AllowAnonymous]
public async Task<IActionResult> EmergencyPasswordReset(string confirm, string secret)
{
string text = Environment.GetEnvironmentVariable("EMERGENCY_RESET_SECRET") ?? "skyart-emergency-2025";
if (secret != text)
{
return NotFound();
}
if (confirm != "yes-reset-now")
{
return Content("Add ?confirm=yes-reset-now&secret=YOUR_SECRET to URL to reset admin password");
}
string email = "admin@skyartshop.com";
string newPassword = "Admin123!";
AdminUser adminUser = await _pgService.GetUserByEmailAsync(email);
if (adminUser == null)
{
adminUser = new AdminUser
{
Email = email,
Name = "System Administrator",
Role = "MasterAdmin",
Permissions = new List<string>
{
"manage_users", "manage_products", "manage_orders", "manage_content", "manage_settings", "view_reports", "manage_finances", "manage_inventory", "manage_customers", "manage_blog",
"manage_portfolio", "manage_pages"
},
IsActive = true,
CreatedBy = "Emergency Reset",
CreatedAt = DateTime.UtcNow
};
}
adminUser.PasswordHash = _pgAuthService.HashPassword(newPassword);
adminUser.LastLogin = DateTime.UtcNow;
await _pgService.CreateAdminUserAsync(adminUser);
return Content($"\r\n<!DOCTYPE html>\r\n<html>\r\n<head>\r\n <title>Password Reset Complete</title>\r\n <style>\r\n body {{ font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }}\r\n .success {{ background: #d4edda; border: 1px solid #c3e6cb; padding: 20px; border-radius: 5px; }}\r\n .credentials {{ background: #f8f9fa; padding: 15px; margin: 20px 0; border-left: 4px solid #28a745; }}\r\n a {{ color: #007bff; text-decoration: none; }}\r\n </style>\r\n</head>\r\n<body>\r\n <div class='success'>\r\n <h2>✓ Password Reset Successful</h2>\r\n <p>The admin password has been reset.</p>\r\n <div class='credentials'>\r\n <strong>Login Credentials:</strong><br>\r\n Email: <code>{email}</code><br>\r\n Password: <code>{newPassword}</code>\r\n </div>\r\n <p><a href='/admin/login'>→ Go to Login Page</a></p>\r\n <p><small>For security, this URL will be disabled after first successful login.</small></p>\r\n </div>\r\n</body>\r\n</html>\r\n", "text/html");
}
[HttpPost("change-password")]
public async Task<IActionResult> ChangePassword(string currentPassword, string newPassword, string confirmPassword)
{
if (string.IsNullOrWhiteSpace(currentPassword) || string.IsNullOrWhiteSpace(newPassword))
{
base.ViewBag.Error = "All fields are required";
return View();
}
if (newPassword != confirmPassword)
{
base.ViewBag.Error = "New password and confirmation do not match";
return View();
}
if (newPassword.Length < 6)
{
base.ViewBag.Error = "Password must be at least 6 characters";
return View();
}
string text = base.User.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value;
if (string.IsNullOrEmpty(text))
{
base.ViewBag.Error = "User not found";
return View();
}
AdminUser adminUser = await _pgService.GetByIdAsync<AdminUser>("AdminUsers", text);
if (adminUser == null || !_pgAuthService.VerifyPassword(currentPassword, adminUser.PasswordHash))
{
base.ViewBag.Error = "Current password is incorrect";
return View();
}
base.ViewBag.Info = "Password change temporarily disabled during migration. Contact system admin.";
return View();
}
}