Slight refactor and finish enforcement on endpoints

This commit is contained in:
FeTetra 2024-12-23 00:30:37 -05:00
commit f6cbafd524
7 changed files with 78 additions and 35 deletions

View file

@ -34,16 +34,15 @@ public class CommentController : ControllerBase
public async Task<IActionResult> RateComment([FromQuery] int commentId, [FromQuery] int rating, string? username, string? slotType, int slotId) public async Task<IActionResult> RateComment([FromQuery] int commentId, [FromQuery] int rating, string? username, string? slotType, int slotId)
{ {
GameTokenEntity token = this.GetToken(); GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token); UserEntity? user = await this.database.UserFromGameToken(token);
if (user == null) return this.Unauthorized(); if (user == null) return this.Unauthorized();
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
// Return bad request if both are true or both are false // Return bad request if both are true or both are false
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest(); if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
bool success = await this.database.RateComment(token.UserId, commentId, rating); bool success = await this.database.RateComment(token.UserId, commentId, rating);
if (!success) return this.BadRequest(); if (!success) return this.BadRequest();
@ -55,15 +54,14 @@ public class CommentController : ControllerBase
public async Task<IActionResult> GetComments(string? username, string? slotType, int slotId) public async Task<IActionResult> GetComments(string? username, string? slotType, int slotId)
{ {
GameTokenEntity token = this.GetToken(); GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token);
UserEntity? user = await this.database.UserFromGameToken(token);
if (user == null) return this.Unauthorized(); if (user == null) return this.Unauthorized();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest(); // Return bad request on unverified email if enforcement is enabled
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest(); if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
int originalSlotId = slotId; int originalSlotId = slotId;
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer); if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
@ -108,8 +106,7 @@ public class CommentController : ControllerBase
.ApplyPagination(pageData) .ApplyPagination(pageData)
.ToListAsync()).ToSerializableList(c => GameComment.CreateFromEntity(c, token.UserId)); .ToListAsync()).ToSerializableList(c => GameComment.CreateFromEntity(c, token.UserId));
if (type == CommentType.Level && slotType == "developer" && user.IsModerator && pageData.PageStart == 1) if (type == CommentType.Level && slotType == "developer" && user.IsModerator && pageData.PageStart == 1) {
{
comments.Insert(0, new GameComment comments.Insert(0, new GameComment
{ {
CommentId = 0, CommentId = 0,
@ -127,16 +124,15 @@ public class CommentController : ControllerBase
public async Task<IActionResult> PostComment(string? username, string? slotType, int slotId) public async Task<IActionResult> PostComment(string? username, string? slotType, int slotId)
{ {
GameTokenEntity token = this.GetToken(); GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token); UserEntity? user = await this.database.UserFromGameToken(token);
if (user == null) return this.Unauthorized(); if (user == null) return this.Unauthorized();
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
// Deny request if in read-only mode // Deny request if in read-only mode
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest(); if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
GameComment? comment = await this.DeserializeBody<GameComment>(); GameComment? comment = await this.DeserializeBody<GameComment>();
if (comment?.Message == null) return this.BadRequest(); if (comment?.Message == null) return this.BadRequest();
@ -172,17 +168,16 @@ public class CommentController : ControllerBase
public async Task<IActionResult> DeleteComment([FromQuery] int commentId, string? username, string? slotType, int slotId) public async Task<IActionResult> DeleteComment([FromQuery] int commentId, string? username, string? slotType, int slotId)
{ {
GameTokenEntity token = this.GetToken(); GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token); UserEntity? user = await this.database.UserFromGameToken(token);
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
// Deny request if in read-only mode // Deny request if in read-only mode
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest(); if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest(); if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
CommentEntity? comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId); CommentEntity? comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId);
if (comment == null) return this.NotFound(); if (comment == null) return this.NotFound();

View file

@ -24,8 +24,6 @@ public class EnterLevelController : ControllerBase
{ {
private readonly DatabaseContext database; private readonly DatabaseContext database;
private static readonly bool emailEnforcementEnabled = EnforceEmailConfiguration.Instance.EnableEmailEnforcement;
public EnterLevelController(DatabaseContext database) public EnterLevelController(DatabaseContext database)
{ {
this.database = database; this.database = database;
@ -41,9 +39,6 @@ public class EnterLevelController : ControllerBase
if (SlotHelper.IsTypeInvalid(slotType)) return this.BadRequest(); if (SlotHelper.IsTypeInvalid(slotType)) return this.BadRequest();
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
// don't count plays for developer slots // don't count plays for developer slots
if (slotType == "developer") return this.Ok(); if (slotType == "developer") return this.Ok();
@ -117,9 +112,6 @@ public class EnterLevelController : ControllerBase
if (SlotHelper.IsTypeInvalid(slotType)) return this.BadRequest(); if (SlotHelper.IsTypeInvalid(slotType)) return this.BadRequest();
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
if (slotType == "developer") return this.Ok(); if (slotType == "developer") return this.Ok();
SlotEntity? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slotId); SlotEntity? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slotId);

View file

@ -41,7 +41,6 @@ public class MatchController : ControllerBase
public async Task<IActionResult> Match() public async Task<IActionResult> Match()
{ {
GameTokenEntity token = this.GetToken(); GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token); UserEntity? user = await this.database.UserFromGameToken(token);
if (user == null) return this.Unauthorized(); if (user == null) return this.Unauthorized();

View file

@ -27,6 +27,8 @@ public class PhotosController : ControllerBase
{ {
private readonly DatabaseContext database; private readonly DatabaseContext database;
private static readonly bool emailEnforcementEnabled = EnforceEmailConfiguration.Instance.EnableEmailEnforcement;
public PhotosController(DatabaseContext database) public PhotosController(DatabaseContext database)
{ {
this.database = database; this.database = database;
@ -36,6 +38,11 @@ public class PhotosController : ControllerBase
public async Task<IActionResult> UploadPhoto() public async Task<IActionResult> UploadPhoto()
{ {
GameTokenEntity token = this.GetToken(); GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token);
if (user == null) return this.Unauthorized();
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
// Deny request if in read-only mode // Deny request if in read-only mode
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest(); if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
@ -174,6 +181,11 @@ public class PhotosController : ControllerBase
[HttpGet("photos/{slotType}/{id:int}")] [HttpGet("photos/{slotType}/{id:int}")]
public async Task<IActionResult> SlotPhotos(string slotType, int id, [FromQuery] string? by) public async Task<IActionResult> SlotPhotos(string slotType, int id, [FromQuery] string? by)
{ {
GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token);
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
if (SlotHelper.IsTypeInvalid(slotType)) return this.BadRequest(); if (SlotHelper.IsTypeInvalid(slotType)) return this.BadRequest();
@ -202,7 +214,6 @@ public class PhotosController : ControllerBase
[HttpGet("photos/by")] [HttpGet("photos/by")]
public async Task<IActionResult> UserPhotosBy(string user) public async Task<IActionResult> UserPhotosBy(string user)
{ {
int targetUserId = await this.database.UserIdFromUsername(user); int targetUserId = await this.database.UserIdFromUsername(user);
if (targetUserId == 0) return this.NotFound(); if (targetUserId == 0) return this.NotFound();
@ -218,7 +229,7 @@ public class PhotosController : ControllerBase
[HttpGet("photos/with")] [HttpGet("photos/with")]
public async Task<IActionResult> UserPhotosWith(string user) public async Task<IActionResult> UserPhotosWith(string user)
{ {
int targetUserId = await this.database.UserIdFromUsername(user); int targetUserId = await this.database.UserIdFromUsername(user);
if (targetUserId == 0) return this.NotFound(); if (targetUserId == 0) return this.NotFound();
@ -237,6 +248,10 @@ public class PhotosController : ControllerBase
public async Task<IActionResult> DeletePhoto(int id) public async Task<IActionResult> DeletePhoto(int id)
{ {
GameTokenEntity token = this.GetToken(); GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token);
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
PhotoEntity? photo = await this.database.Photos.FirstOrDefaultAsync(p => p.PhotoId == id); PhotoEntity? photo = await this.database.Photos.FirstOrDefaultAsync(p => p.PhotoId == id);
if (photo == null) return this.NotFound(); if (photo == null) return this.NotFound();

View file

@ -1,12 +1,15 @@
#nullable enable #nullable enable
using System.Text; using System.Text;
using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Extensions; using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Files; using LBPUnion.ProjectLighthouse.Files;
using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.Logging;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Misc; using LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Misc;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Logging; using LBPUnion.ProjectLighthouse.Types.Logging;
using LBPUnion.ProjectLighthouse.Types.Resources; using LBPUnion.ProjectLighthouse.Types.Resources;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using IOFile = System.IO.File; using IOFile = System.IO.File;
@ -19,10 +22,18 @@ namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Resources;
[Route("LITTLEBIGPLANETPS3_XML")] [Route("LITTLEBIGPLANETPS3_XML")]
public class ResourcesController : ControllerBase public class ResourcesController : ControllerBase
{ {
private readonly DatabaseContext database;
public ResourcesController(DatabaseContext database)
{
this.database = database;
}
[HttpPost("showModerated")] [HttpPost("showModerated")]
public IActionResult ShowModerated() => this.Ok(new ResourceList()); public IActionResult ShowModerated() => this.Ok(new ResourceList());
private static readonly bool emailEnforcementEnabled = EnforceEmailConfiguration.Instance.EnableEmailEnforcement;
[HttpPost("filterResources")] [HttpPost("filterResources")]
[HttpPost("showNotUploaded")] [HttpPost("showNotUploaded")]
public async Task<IActionResult> FilterResources() public async Task<IActionResult> FilterResources()
@ -36,8 +47,14 @@ public class ResourcesController : ControllerBase
} }
[HttpGet("r/{hash}")] [HttpGet("r/{hash}")]
public IActionResult GetResource(string hash) public async Task<IActionResult> GetResource(string hash)
{ {
GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token);
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
string path = FileHelper.GetResourcePath(hash); string path = FileHelper.GetResourcePath(hash);
string fullPath = Path.GetFullPath(path); string fullPath = Path.GetFullPath(path);
@ -54,6 +71,12 @@ public class ResourcesController : ControllerBase
[HttpPost("upload/{hash}")] [HttpPost("upload/{hash}")]
public async Task<IActionResult> UploadResource(string hash) public async Task<IActionResult> UploadResource(string hash)
{ {
GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token);
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
string assetsDirectory = FileHelper.ResourcePath; string assetsDirectory = FileHelper.ResourcePath;
string path = FileHelper.GetResourcePath(hash); string path = FileHelper.GetResourcePath(hash);
string fullPath = Path.GetFullPath(path); string fullPath = Path.GetFullPath(path);

View file

@ -29,6 +29,8 @@ public class UserController : ControllerBase
{ {
private readonly DatabaseContext database; private readonly DatabaseContext database;
private static readonly bool emailEnforcementEnabled = EnforceEmailConfiguration.Instance.EnableEmailEnforcement;
public UserController(DatabaseContext database) public UserController(DatabaseContext database)
{ {
this.database = database; this.database = database;
@ -36,7 +38,11 @@ public class UserController : ControllerBase
[HttpGet("user/{username}")] [HttpGet("user/{username}")]
public async Task<IActionResult> GetUser(string username) public async Task<IActionResult> GetUser(string username)
{ {
// Return bad request on unverified email if enforcement is enabled
GameTokenEntity token = this.GetToken();
if (emailEnforcementEnabled && !token.User.EmailAddressVerified) return this.BadRequest();
UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username); UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
if (user == null) return this.NotFound(); if (user == null) return this.NotFound();
@ -66,9 +72,11 @@ public class UserController : ControllerBase
public async Task<IActionResult> UpdateUser() public async Task<IActionResult> UpdateUser()
{ {
GameTokenEntity token = this.GetToken(); GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token); UserEntity? user = await this.database.UserFromGameToken(token);
if (user == null) return this.Forbid(); if (user == null) return this.Forbid();
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
UserUpdate? update = await this.DeserializeBody<UserUpdate>("updateUser", "user"); UserUpdate? update = await this.DeserializeBody<UserUpdate>("updateUser", "user");
@ -176,6 +184,9 @@ public class UserController : ControllerBase
UserEntity? user = await this.database.UserFromGameToken(this.GetToken()); UserEntity? user = await this.database.UserFromGameToken(this.GetToken());
if (user == null) return this.Forbid(); if (user == null) return this.Forbid();
// Return bad request on unverified email if enforcement is enabled
if (emailEnforcementEnabled && !user.EmailAddressVerified) return this.BadRequest();
string bodyString = await this.ReadBodyAsync(); string bodyString = await this.ReadBodyAsync();
Pins? pinJson = JsonSerializer.Deserialize<Pins>(bodyString); Pins? pinJson = JsonSerializer.Deserialize<Pins>(bodyString);

View file

@ -9,8 +9,10 @@ using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Extensions; using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Logging;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token; using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Logging;
using LBPUnion.ProjectLighthouse.Types.Mail; using LBPUnion.ProjectLighthouse.Types.Mail;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -91,7 +93,13 @@ public static class SMTPHelper
string domain = email.Split('@')[1]; string domain = email.Split('@')[1];
// Return false if domain is found in blacklist // Return false if domain is found in blacklist
return !blacklistedDomains.Contains(domain); if (blacklistedDomains.Contains(domain))
{
Logger.Info($"Invalid email address {email} submitted by user.", LogArea.Email);
return false;
}
return true;
} }
return true; return true;