using System; using System.Linq; using System.Threading.Tasks; using API.Data; using API.Data.Repositories; using API.Extensions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.DependencyInjection; namespace API.Middleware; /// /// An attribute to restrict endpoint usage to either the user itself (authenticated user == userId) or the /// requested user is sharing their profile. /// Returns 400 BadRequest on failure /// /// Defaults to userId [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class ProfilePrivacyAttribute(string queryKey = "userId", bool allowMissingUserId = false) : Attribute, IAsyncAuthorizationFilter { public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { var userIdString = context.HttpContext.Request.Query[queryKey].FirstOrDefault(); if (string.IsNullOrEmpty(userIdString)) { if (allowMissingUserId) { return; } context.Result = new ContentResult { StatusCode = StatusCodes.Status400BadRequest, ContentType = "text/plain", }; return; } var userId = int.Parse(userIdString); var user = context.HttpContext.User; if (user.GetUserId() == userId) { return; } var unitOfWork = context.HttpContext.RequestServices.GetRequiredService(); var requestedUser = await unitOfWork.UserRepository.GetUserByIdAsync(userId, AppUserIncludes.UserPreferences); if (requestedUser == null || !requestedUser.UserPreferences.SocialPreferences.ShareProfile) { context.Result = new ContentResult { StatusCode = StatusCodes.Status400BadRequest, ContentType = "text/plain", }; } } }