Pdf Ansehen und PDF herunterladen gefixet
This commit is contained in:
@@ -41,7 +41,7 @@
|
||||
</p>
|
||||
<div class="d-flex gap-2">
|
||||
<button class="btn btn-primary btn-sm" @onclick="@(async () => ShowDetail(app))">PDF ansehen</button>
|
||||
<a href="@((NavManager.BaseUri + "api/engineerapplication") + "/download/" + app.ApplicationId + "?moduleid=" + ModuleState.ModuleId)" target="_blank" class="btn btn-outline-secondary btn-sm">Herunterladen</a>
|
||||
<a href="@(PageState.Alias.Path == "" ? "" : "/" + PageState.Alias.Path)/api/file/download/@(app.FileId)/attach" target="_blank" class="btn btn-outline-secondary btn-sm">Herunterladen</a>
|
||||
<button class="btn btn-outline-danger btn-sm" @onclick="@(() => InitReport(app))">Melden</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,12 +64,12 @@ else
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Antrags-PDF (@_selectedApp.FileId)</h5>
|
||||
<h5 class="modal-title">Antrags-PDF</h5>
|
||||
<button type="button" class="btn-close" @onclick="@(() => _selectedApp = null)"></button>
|
||||
</div>
|
||||
<div class="modal-body p-0">
|
||||
<div class="ratio ratio-16x9" style="min-height: 500px;">
|
||||
<iframe src="@((NavManager.BaseUri + "api/engineerapplication") + "/download/" + _selectedApp.ApplicationId + "?moduleid=" + ModuleState.ModuleId)" allowfullscreen></iframe>
|
||||
<div style="min-height: 600px; height: 75vh;">
|
||||
<iframe src="@(PageState.Alias.Path == "" ? "" : "/" + PageState.Alias.Path)/api/file/download/@(_selectedApp.FileId)" style="width: 100%; height: 100%; border: none;" allowfullscreen></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
@@ -43,20 +43,28 @@ namespace SZUAbsolventenverein.Module.PremiumArea.Services
|
||||
return Task.FromResult(_repository.GetEngineerApplications(ModuleId).ToList());
|
||||
}
|
||||
|
||||
// Check if Premium
|
||||
if (IsUserPremium(user))
|
||||
var userId = _accessor.HttpContext.GetUserId();
|
||||
var results = new List<EngineerApplication>();
|
||||
|
||||
// Always include the user's own applications (needed for Apply.razor)
|
||||
if (userId != -1)
|
||||
{
|
||||
// Return Approved AND Published
|
||||
// Repository GetEngineerApplications(ModuleId, status) usually filters by status.
|
||||
// If I want both, I might need 2 calls or update Repository.
|
||||
// Simple approach: Get All and filter here? No, repository likely filters.
|
||||
// Let's call twice and combine for now, or assume Repository supports "Published".
|
||||
var approved = _repository.GetEngineerApplications(ModuleId, "Approved");
|
||||
var published = _repository.GetEngineerApplications(ModuleId, "Published");
|
||||
return Task.FromResult(approved.Union(published).ToList());
|
||||
var ownApps = _repository.GetEngineerApplications(ModuleId)
|
||||
.Where(a => a.UserId == userId).ToList();
|
||||
results.AddRange(ownApps);
|
||||
}
|
||||
|
||||
return Task.FromResult(new List<EngineerApplication>());
|
||||
// Check if Premium - also show approved/published apps from others
|
||||
if (IsUserPremium(user))
|
||||
{
|
||||
var approved = _repository.GetEngineerApplications(ModuleId, "Approved");
|
||||
var published = _repository.GetEngineerApplications(ModuleId, "Published");
|
||||
results.AddRange(approved.Union(published));
|
||||
// Remove duplicates (own apps might already be in approved/published)
|
||||
results = results.GroupBy(a => a.ApplicationId).Select(g => g.First()).ToList();
|
||||
}
|
||||
|
||||
return Task.FromResult(results);
|
||||
}
|
||||
|
||||
public Task<List<EngineerApplication>> GetApplicationsAsync(int ModuleId, string status)
|
||||
@@ -142,19 +150,23 @@ namespace SZUAbsolventenverein.Module.PremiumArea.Services
|
||||
var userId = _accessor.HttpContext.GetUserId();
|
||||
bool isAdmin = _userPermissions.IsAuthorized(user, _alias.SiteId, EntityNames.Module, Application.ModuleId,
|
||||
PermissionNames.Edit);
|
||||
bool isOwner = (userId != -1 && existing.UserId == userId);
|
||||
|
||||
if (isAdmin || (existing.UserId == userId && existing.Status == "Draft")) // Only owner can edit if Draft
|
||||
if (isAdmin || isOwner)
|
||||
{
|
||||
if (!isAdmin)
|
||||
{
|
||||
Application.Status = existing.Status == "Draft" && Application.Status == "Submitted"
|
||||
? "Published"
|
||||
: existing.Status; // Auto-publish on submit
|
||||
// If client sends "Published" (which Apply.razor does), apply it.
|
||||
if (Application.Status == "Published" && existing.Status == "Draft")
|
||||
// Owner can update their own application
|
||||
// Accept "Published" status from client (auto-publish without admin approval)
|
||||
if (Application.Status == "Published")
|
||||
{
|
||||
Application.SubmittedOn = DateTime.UtcNow;
|
||||
Application.ApprovedOn = DateTime.UtcNow;
|
||||
Application.SubmittedOn ??= DateTime.UtcNow;
|
||||
Application.ApprovedOn ??= DateTime.UtcNow;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep existing status if client didn't explicitly set to Published
|
||||
Application.Status = existing.Status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +176,9 @@ namespace SZUAbsolventenverein.Module.PremiumArea.Services
|
||||
return Task.FromResult(Application);
|
||||
}
|
||||
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security,
|
||||
"Unauthorized Update Attempt. UserId: {UserId}, AppOwner: {OwnerId}, IsAdmin: {IsAdmin}",
|
||||
userId, existing.UserId, isAdmin);
|
||||
return Task.FromResult<EngineerApplication>(null);
|
||||
}
|
||||
|
||||
@@ -265,41 +280,21 @@ namespace SZUAbsolventenverein.Module.PremiumArea.Services
|
||||
|
||||
private bool IsUserPremium(System.Security.Claims.ClaimsPrincipal user)
|
||||
{
|
||||
// Oqtane's GetUserId() extension returns -1 if not found.
|
||||
// We need to parse User object myself or use "User.Identity.Name" to find user if needed.
|
||||
// But _premiumService.IsPremium(userId) asks for Int.
|
||||
// I'll assume I can get UserId.
|
||||
// Since Oqtane is weird with Claims sometimes, I'll use the Helper Extension `GetUserId()`.
|
||||
// But wait, "GetUserId" is an extension on HttpContext or ClaimsPrincipal?
|
||||
// In Oqtane.Shared.UserSecurity class? Or Oqtane.Extensions?
|
||||
// Usually `_accessor.HttpContext.GlobalUserId()` ??
|
||||
// Let's rely on standard DI/Context.
|
||||
if (!user.Identity.IsAuthenticated)
|
||||
return false;
|
||||
|
||||
// NOTE: IsUserPremium check requires querying the DB via PremiumService.
|
||||
// This could be expensive on every list call. Caching might be better but for now DB is fine.
|
||||
|
||||
// To get UserId from ClaimsPrincipal:
|
||||
// var userId = int.Parse(user.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier).Value);
|
||||
// I will use `_accessor.HttpContext.GetUserId()` from `Oqtane.Infrastructure` or similar if available.
|
||||
// Since I am already using `_accessor`, I'll rely on Oqtane extensions being available.
|
||||
// Check 1: Oqtane role "Premium Member" (matches the UI-level check in ApplicationList.razor)
|
||||
if (user.IsInRole("Premium Member"))
|
||||
return true;
|
||||
|
||||
// Check 2: Custom UserPremium DB table (for premium granted via GrantPremium/payment)
|
||||
int userId = -1;
|
||||
// Trying standard Oqtane way which is usually:
|
||||
if (user.Identity.IsAuthenticated)
|
||||
{
|
||||
// Using Oqtane.Shared.PrincipalExtensions?
|
||||
// Let's just try to parse NameIdentifier if GetUserId() is not available in my context.
|
||||
// But wait, `ModuleControllerBase` has `User` property.
|
||||
// Here I am in a Service.
|
||||
|
||||
// I will write a helper to safely get UserId.
|
||||
var claim = user.Claims.FirstOrDefault(item =>
|
||||
item.Type == System.Security.Claims.ClaimTypes.NameIdentifier);
|
||||
if (claim != null)
|
||||
{
|
||||
int.TryParse(claim.Value, out userId);
|
||||
}
|
||||
}
|
||||
|
||||
if (userId != -1)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user