Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 14 additions & 15 deletions Refresh.Core/Helpers/ResourceValidationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,37 @@ public static ValidatedAssetResult ValidateReference(AssetValidationParameters p
GameAsset? asset = null;
bool existsInDataStore = false;
bool isPSP = parameters.GameToUseIn == TokenGame.LittleBigPlanetPSP;
Action<string>? onNewAssetRefCallback = parameters.OnNewAssetRefCallback;

if (parameters.AssetRef.IsBlankHash())
{
if (!parameters.MayBeBlank) return new(BadRequest, "0", $"The {assetTypeStr} must be set.", onNewAssetRefCallback);
else return new(OK, "0", null, onNewAssetRefCallback);
if (!parameters.MayBeBlank) return new(BadRequest, "0", $"The {assetTypeStr} must be set.");
else return new(OK, "0", null);
}

else if (parameters.AssetRef.StartsWith('g'))
{
if (!parameters.MayBeGuid) return new(BadRequest, null, $"The {assetTypeStr} may not be an in-game asset.", onNewAssetRefCallback);
if (parameters.AssetRef.Length < 2) return new(BadRequest, null, $"The used in-game {assetTypeStr} is invalid (empty GUID).", onNewAssetRefCallback);
if (!parameters.MayBeGuid) return new(BadRequest, null, $"The {assetTypeStr} may not be an in-game asset.");
if (parameters.AssetRef.Length < 2) return new(BadRequest, null, $"The used in-game {assetTypeStr} is invalid (empty GUID).");

// This should only happen if the user is messing with mods/the API/beta builds, so give them a more detailed response
bool canParseGuid = long.TryParse(parameters.AssetRef[1..], out long guid);
if (!canParseGuid)
return new(BadRequest, null, $"The used in-game {assetTypeStr} is invalid (badly formatted GUID).", onNewAssetRefCallback);
return new(BadRequest, null, $"The used in-game {assetTypeStr} is invalid (badly formatted GUID).");

if (parameters.MustBeTexture && !parameters.GuidChecker.IsTextureGuid(parameters.GameToUseIn, guid))
return new(BadRequest, null, $"The used in-game {assetTypeStr} was not a valid image (unknown GUID).", onNewAssetRefCallback);
return new(BadRequest, null, $"The used in-game {assetTypeStr} was not a valid image (unknown GUID).");
}

// At this point the reference is a hash
else if (!parameters.MayBeHash)
{
return new(BadRequest, null, $"The {assetTypeStr} may not be a custom asset.", onNewAssetRefCallback);
return new(BadRequest, null, $"The {assetTypeStr} may not be a custom asset.");
}

else if (!CommonPatterns.Sha1Regex().IsMatch(parameters.AssetRef))
{
// This should only happen if a player is messing with mods/the API, so give them a more detailed response
return new(BadRequest, null, $"The used {assetTypeStr} had an invalid hash.", onNewAssetRefCallback);
return new(BadRequest, null, $"The used {assetTypeStr} had an invalid hash.");
}

else
Expand All @@ -60,7 +59,7 @@ public static ValidatedAssetResult ValidateReference(AssetValidationParameters p
if (disallowed != null)
{
logger.LogWarning(BunkumCategory.UserContent, $"{parameters.User} tried to use a manually disallowed {assetTypeStr}.");
return new(Unauthorized, disallowanceInfo: disallowed, onNewAssetRefCallback: onNewAssetRefCallback);
return new(Unauthorized, disallowanceInfo: disallowed);
}

string filename = isPSP ? $"psp/{parameters.AssetRef}" : parameters.AssetRef;
Expand All @@ -71,7 +70,7 @@ public static ValidatedAssetResult ValidateReference(AssetValidationParameters p
logger.LogDebug(BunkumCategory.UserContent, $"Referenced asset '{filename}' could not be found in data store.");

if (parameters.MustBeInDataStoreIfHash)
return new(NotFound, null, $"The used {assetTypeStr} did not exist on the server.", onNewAssetRefCallback);
return new(NotFound, null, $"The used {assetTypeStr} did not exist on the server.");
}

asset = parameters.Cache.GetAssetInfo(parameters.AssetRef, parameters.Database);
Expand All @@ -88,15 +87,15 @@ public static ValidatedAssetResult ValidateReference(AssetValidationParameters p
sw.Stop();
logger.LogError(BunkumCategory.UserContent, $"Failed to read '{filename}' from data store!");
logger.LogDebug(BunkumCategory.UserContent, $"Failed to get '{filename}' after {sw.ElapsedMilliseconds}ms.");
return new(InternalServerError, null, $"Failed to read {assetTypeStr} internally. Please report this to the server owner.", onNewAssetRefCallback, existsInDataStore: existsInDataStore);
return new(InternalServerError, null, $"Failed to read {assetTypeStr} internally. Please report this to the server owner.", existsInDataStore: existsInDataStore);
}

asset = parameters.AssetImporter.ReadAndVerifyAsset(parameters.AssetRef, assetData, parameters.PlatformToUseIn, parameters.Database);
if (asset == null)
{
sw.Stop();
logger.LogDebug(BunkumCategory.UserContent, $"Failed to get '{filename}' after {sw.ElapsedMilliseconds}ms.");
return new(BadRequest, null, $"The used {assetTypeStr} was invalid or corrupt.", onNewAssetRefCallback, existsInDataStore: existsInDataStore);
return new(BadRequest, null, $"The used {assetTypeStr} was invalid or corrupt.", existsInDataStore: existsInDataStore);
}

sw.Stop();
Expand All @@ -109,12 +108,12 @@ public static ValidatedAssetResult ValidateReference(AssetValidationParameters p
bool isHashedTexture = (asset.AssetFlags & AssetFlags.Imagery) != 0;

if (parameters.MustBeTexture && !isHashedTexture)
return new(BadRequest, null, $"The used {assetTypeStr} was not a valid custom image.", onNewAssetRefCallback, assetInfo: asset, existsInDataStore: existsInDataStore);
return new(BadRequest, null, $"The used {assetTypeStr} was not a valid custom image.", assetInfo: asset, existsInDataStore: existsInDataStore);

// TODO: actually use AIPI to scan image if not null
}
}

return new(OK, parameters.AssetRef, null, onNewAssetRefCallback, assetInfo: asset, existsInDataStore: existsInDataStore);
return new(OK, parameters.AssetRef, assetInfo: asset, existsInDataStore: existsInDataStore);
}
}
14 changes: 3 additions & 11 deletions Refresh.Core/Types/Assets/Validation/AssetValidationParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,11 @@ public struct AssetValidationParameters
/// What the asset should be referred as in user-faced error messages and in logs, e.g. "planet asset" or "icon".
/// If null, we will default to calling it "asset" or "image" depending on MustBeTexture.
/// </summary>
public string? AssetContextTypeStr { get; set; }
public string? AssetContextTypeStr { get; set; } // TODO think of a better name

/// <summary>
/// Callback which is called with the new asset reference as parameter when constructing <see cref="ValidatedAssetResult"/>;
/// useful to update asset references of entities during validation without requiring the caller to manually reassign them after validation;
/// this way similar attributes like photo images or face icons can simply be iterated.
/// If null, this will be skipped.
/// </summary>
public Action<string>? OnNewAssetRefCallback { get; set; }

public AssetValidationParameters(string assetKey, DataContext dataContext, AssetImporter assetImporter, AipiService? aipi = null)
public AssetValidationParameters(string assetRef, DataContext dataContext, AssetImporter assetImporter, AipiService? aipi = null)
{
this.AssetRef = assetKey;
this.AssetRef = assetRef;
this.User = dataContext.User;
this.GameToUseIn = dataContext.Game;
this.PlatformToUseIn = dataContext.Platform;
Expand Down
4 changes: 1 addition & 3 deletions Refresh.Core/Types/Assets/Validation/ValidatedAssetResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public struct ValidatedAssetResult
public DisallowedAsset? DisallowanceInfo { get; set; }
public bool ExistsInDataStore { get; set; }

public ValidatedAssetResult(HttpStatusCode status, string? newAssetRef = null, string? errorMessage = null, Action<string>? onNewAssetRefCallback = null,
public ValidatedAssetResult(HttpStatusCode status, string? newAssetRef = null, string? errorMessage = null,
GameAsset? assetInfo = null, DisallowedAsset? disallowanceInfo = null, bool existsInDataStore = false)
{
this.Status = status;
Expand All @@ -35,7 +35,5 @@ public ValidatedAssetResult(HttpStatusCode status, string? newAssetRef = null, s
this.AssetInfo = assetInfo;
this.DisallowanceInfo = disallowanceInfo;
this.ExistsInDataStore = existsInDataStore;

onNewAssetRefCallback?.Invoke(this.NewAssetRef);
}
}
Loading
Loading