Collections needs to honour the logged in users age rating permissionFixes #273

Known issue: #275
This commit is contained in:
Michael Green
2024-01-31 07:28:07 +11:00
committed by GitHub
parent f65408a64d
commit 5f6a71e065
10 changed files with 421 additions and 224 deletions

View File

@@ -7,33 +7,26 @@ using System.Security.Cryptography;
using Authentication;
using gaseous_server.Classes.Metadata;
using gaseous_server.Controllers;
using gaseous_server.Controllers.v1_1;
using gaseous_server.Models;
using IGDB.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using SharpCompress.Common;
using static gaseous_server.Classes.Metadata.Games;
namespace gaseous_server.Classes
{
public class Collections
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
public Collections(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
public static List<CollectionItem> GetCollections() {
public static List<CollectionItem> GetCollections(string userid) {
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT * FROM RomCollections ORDER BY `Name`";
DataTable data = db.ExecuteCMD(sql);
string sql = "SELECT * FROM RomCollections WHERE OwnedBy=@ownedby ORDER BY `Name`";
Dictionary<string, object> dbDict = new Dictionary<string, object>{
{ "ownedby", userid }
};
DataTable data = db.ExecuteCMD(sql, dbDict);
List<CollectionItem> collectionItems = new List<CollectionItem>();
@@ -44,11 +37,24 @@ namespace gaseous_server.Classes
return collectionItems;
}
public static CollectionItem GetCollection(long Id) {
public static CollectionItem GetCollection(long Id, string userid) {
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT * FROM RomCollections WHERE Id = @id ORDER BY `Name`";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", Id);
string sql;
if (userid == "")
{
// reserved for internal operations
sql = "SELECT * FROM RomCollections WHERE Id = @id ORDER BY `Name`";
}
else
{
// instigated by a user
sql = "SELECT * FROM RomCollections WHERE Id = @id AND OwnedBy = @ownedby ORDER BY `Name`";
}
Dictionary<string, object> dbDict = new Dictionary<string, object>
{
{ "id", Id },
{ "ownedby", userid }
};
DataTable romDT = db.ExecuteCMD(sql, dbDict);
if (romDT.Rows.Count > 0)
@@ -64,60 +70,66 @@ namespace gaseous_server.Classes
}
}
public static CollectionItem NewCollection(CollectionItem item)
public static CollectionItem NewCollection(CollectionItem item, string userid)
{
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "INSERT INTO RomCollections (`Name`, Description, Platforms, Genres, Players, PlayerPerspectives, Themes, MinimumRating, MaximumRating, MaximumRomsPerPlatform, MaximumBytesPerPlatform, MaximumCollectionSizeInBytes, FolderStructure, IncludeBIOSFiles, ArchiveType, AlwaysInclude, BuiltStatus) VALUES (@name, @description, @platforms, @genres, @players, @playerperspectives, @themes, @minimumrating, @maximumrating, @maximumromsperplatform, @maximumbytesperplatform, @maximumcollectionsizeinbytes, @folderstructure, @includebiosfiles, @archivetype, @alwaysinclude, @builtstatus); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("name", item.Name);
dbDict.Add("description", item.Description);
dbDict.Add("platforms", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Platforms, new List<long>())));
dbDict.Add("genres", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Genres, new List<long>())));
dbDict.Add("players", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Players, new List<long>())));
dbDict.Add("playerperspectives", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.PlayerPerspectives, new List<long>())));
dbDict.Add("themes", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Themes, new List<long>())));
dbDict.Add("minimumrating", Common.ReturnValueIfNull(item.MinimumRating, -1));
dbDict.Add("maximumrating", Common.ReturnValueIfNull(item.MaximumRating, -1));
dbDict.Add("maximumromsperplatform", Common.ReturnValueIfNull(item.MaximumRomsPerPlatform, -1));
dbDict.Add("maximumbytesperplatform", Common.ReturnValueIfNull(item.MaximumBytesPerPlatform, -1));
dbDict.Add("maximumcollectionsizeinbytes", Common.ReturnValueIfNull(item.MaximumCollectionSizeInBytes, -1));
dbDict.Add("folderstructure", Common.ReturnValueIfNull(item.FolderStructure, CollectionItem.FolderStructures.Gaseous));
dbDict.Add("includebiosfiles", Common.ReturnValueIfNull(item.IncludeBIOSFiles, 0));
dbDict.Add("archivetype", Common.ReturnValueIfNull(item.ArchiveType, CollectionItem.ArchiveTypes.Zip));
dbDict.Add("alwaysinclude", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.AlwaysInclude, new List<CollectionItem.AlwaysIncludeItem>())));
dbDict.Add("builtstatus", CollectionItem.CollectionBuildStatus.WaitingForBuild);
string sql = "INSERT INTO RomCollections (`Name`, Description, Platforms, Genres, Players, PlayerPerspectives, Themes, MinimumRating, MaximumRating, MaximumRomsPerPlatform, MaximumBytesPerPlatform, MaximumCollectionSizeInBytes, FolderStructure, IncludeBIOSFiles, ArchiveType, AlwaysInclude, BuiltStatus, OwnedBy) VALUES (@name, @description, @platforms, @genres, @players, @playerperspectives, @themes, @minimumrating, @maximumrating, @maximumromsperplatform, @maximumbytesperplatform, @maximumcollectionsizeinbytes, @folderstructure, @includebiosfiles, @archivetype, @alwaysinclude, @builtstatus, @ownedby); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
Dictionary<string, object> dbDict = new Dictionary<string, object>
{
{ "name", item.Name },
{ "description", item.Description },
{ "platforms", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Platforms, new List<long>())) },
{ "genres", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Genres, new List<long>())) },
{ "players", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Players, new List<long>())) },
{ "playerperspectives", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.PlayerPerspectives, new List<long>())) },
{ "themes", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Themes, new List<long>())) },
{ "minimumrating", Common.ReturnValueIfNull(item.MinimumRating, -1) },
{ "maximumrating", Common.ReturnValueIfNull(item.MaximumRating, -1) },
{ "maximumromsperplatform", Common.ReturnValueIfNull(item.MaximumRomsPerPlatform, -1) },
{ "maximumbytesperplatform", Common.ReturnValueIfNull(item.MaximumBytesPerPlatform, -1) },
{ "maximumcollectionsizeinbytes", Common.ReturnValueIfNull(item.MaximumCollectionSizeInBytes, -1) },
{ "folderstructure", Common.ReturnValueIfNull(item.FolderStructure, CollectionItem.FolderStructures.Gaseous) },
{ "includebiosfiles", Common.ReturnValueIfNull(item.IncludeBIOSFiles, 0) },
{ "archivetype", Common.ReturnValueIfNull(item.ArchiveType, CollectionItem.ArchiveTypes.Zip) },
{ "alwaysinclude", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.AlwaysInclude, new List<CollectionItem.AlwaysIncludeItem>())) },
{ "builtstatus", CollectionItem.CollectionBuildStatus.WaitingForBuild },
{ "ownedby", userid }
};
DataTable romDT = db.ExecuteCMD(sql, dbDict);
long CollectionId = (long)romDT.Rows[0][0];
CollectionItem collectionItem = GetCollection(CollectionId);
CollectionItem collectionItem = GetCollection(CollectionId, userid);
StartCollectionItemBuild(CollectionId);
StartCollectionItemBuild(CollectionId, userid);
return collectionItem;
}
public static CollectionItem EditCollection(long Id, CollectionItem item, bool ForceRebuild = true)
public static CollectionItem EditCollection(long Id, CollectionItem item, string userid, bool ForceRebuild = true)
{
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "UPDATE RomCollections SET `Name`=@name, Description=@description, Platforms=@platforms, Genres=@genres, Players=@players, PlayerPerspectives=@playerperspectives, Themes=@themes, MinimumRating=@minimumrating, MaximumRating=@maximumrating, MaximumRomsPerPlatform=@maximumromsperplatform, MaximumBytesPerPlatform=@maximumbytesperplatform, MaximumCollectionSizeInBytes=@maximumcollectionsizeinbytes, FolderStructure=@folderstructure, IncludeBIOSFiles=@includebiosfiles, ArchiveType=@archivetype, AlwaysInclude=@alwaysinclude, BuiltStatus=@builtstatus WHERE Id=@id";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", Id);
dbDict.Add("name", item.Name);
dbDict.Add("description", item.Description);
dbDict.Add("platforms", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Platforms, new List<long>())));
dbDict.Add("genres", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Genres, new List<long>())));
dbDict.Add("players", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Players, new List<long>())));
dbDict.Add("playerperspectives", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.PlayerPerspectives, new List<long>())));
dbDict.Add("themes", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Themes, new List<long>())));
dbDict.Add("minimumrating", Common.ReturnValueIfNull(item.MinimumRating, -1));
dbDict.Add("maximumrating", Common.ReturnValueIfNull(item.MaximumRating, -1));
dbDict.Add("maximumromsperplatform", Common.ReturnValueIfNull(item.MaximumRomsPerPlatform, -1));
dbDict.Add("maximumbytesperplatform", Common.ReturnValueIfNull(item.MaximumBytesPerPlatform, -1));
dbDict.Add("maximumcollectionsizeinbytes", Common.ReturnValueIfNull(item.MaximumCollectionSizeInBytes, -1));
dbDict.Add("folderstructure", Common.ReturnValueIfNull(item.FolderStructure, CollectionItem.FolderStructures.Gaseous));
dbDict.Add("includebiosfiles", Common.ReturnValueIfNull(item.IncludeBIOSFiles, 0));
dbDict.Add("alwaysinclude", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.AlwaysInclude, new List<CollectionItem.AlwaysIncludeItem>())));
dbDict.Add("archivetype", Common.ReturnValueIfNull(item.ArchiveType, CollectionItem.ArchiveTypes.Zip));
string sql = "UPDATE RomCollections SET `Name`=@name, Description=@description, Platforms=@platforms, Genres=@genres, Players=@players, PlayerPerspectives=@playerperspectives, Themes=@themes, MinimumRating=@minimumrating, MaximumRating=@maximumrating, MaximumRomsPerPlatform=@maximumromsperplatform, MaximumBytesPerPlatform=@maximumbytesperplatform, MaximumCollectionSizeInBytes=@maximumcollectionsizeinbytes, FolderStructure=@folderstructure, IncludeBIOSFiles=@includebiosfiles, ArchiveType=@archivetype, AlwaysInclude=@alwaysinclude, BuiltStatus=@builtstatus WHERE Id=@id AND OwnedBy=@ownedby";
Dictionary<string, object> dbDict = new Dictionary<string, object>
{
{ "id", Id },
{ "name", item.Name },
{ "description", item.Description },
{ "platforms", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Platforms, new List<long>())) },
{ "genres", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Genres, new List<long>())) },
{ "players", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Players, new List<long>())) },
{ "playerperspectives", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.PlayerPerspectives, new List<long>())) },
{ "themes", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Themes, new List<long>())) },
{ "minimumrating", Common.ReturnValueIfNull(item.MinimumRating, -1) },
{ "maximumrating", Common.ReturnValueIfNull(item.MaximumRating, -1) },
{ "maximumromsperplatform", Common.ReturnValueIfNull(item.MaximumRomsPerPlatform, -1) },
{ "maximumbytesperplatform", Common.ReturnValueIfNull(item.MaximumBytesPerPlatform, -1) },
{ "maximumcollectionsizeinbytes", Common.ReturnValueIfNull(item.MaximumCollectionSizeInBytes, -1) },
{ "folderstructure", Common.ReturnValueIfNull(item.FolderStructure, CollectionItem.FolderStructures.Gaseous) },
{ "includebiosfiles", Common.ReturnValueIfNull(item.IncludeBIOSFiles, 0) },
{ "alwaysinclude", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.AlwaysInclude, new List<CollectionItem.AlwaysIncludeItem>())) },
{ "archivetype", Common.ReturnValueIfNull(item.ArchiveType, CollectionItem.ArchiveTypes.Zip) },
{ "ownedby", userid }
};
string CollectionZipFile = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + item.ArchiveExtension);
if (ForceRebuild == true)
@@ -142,22 +154,25 @@ namespace gaseous_server.Classes
}
db.ExecuteCMD(sql, dbDict);
CollectionItem collectionItem = GetCollection(Id);
CollectionItem collectionItem = GetCollection(Id, userid);
if (collectionItem.BuildStatus == CollectionItem.CollectionBuildStatus.WaitingForBuild)
{
StartCollectionItemBuild(Id);
StartCollectionItemBuild(Id, userid);
}
return collectionItem;
}
public static void DeleteCollection(long Id)
public static void DeleteCollection(long Id, string userid)
{
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "DELETE FROM RomCollections WHERE Id=@id";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", Id);
string sql = "DELETE FROM RomCollections WHERE Id=@id AND OwnedBy=@ownedby";
Dictionary<string, object> dbDict = new Dictionary<string, object>
{
{ "id", Id },
{ "ownedby", userid }
};
db.ExecuteCMD(sql, dbDict);
string CollectionZipFile = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + ".zip");
@@ -167,9 +182,10 @@ namespace gaseous_server.Classes
}
}
public static void StartCollectionItemBuild(long Id)
public static void StartCollectionItemBuild(long Id, string userid)
{
CollectionItem collectionItem = GetCollection(Id);
// send blank user id to getcollection as this is not a user initiated process
CollectionItem collectionItem = GetCollection(Id, userid);
if (collectionItem.BuildStatus != CollectionItem.CollectionBuildStatus.Building)
{
@@ -183,13 +199,40 @@ namespace gaseous_server.Classes
// start background task
ProcessQueue.QueueItem queueItem = new ProcessQueue.QueueItem(ProcessQueue.QueueItemType.CollectionCompiler, 1, false, true);
queueItem.Options = Id;
queueItem.Options = new Dictionary<string, object>{
{ "Id", Id },
{ "UserId", userid }
};
queueItem.ForceExecute();
ProcessQueue.QueueItems.Add(queueItem);
}
}
public static CollectionContents GetCollectionContent(CollectionItem collectionItem) {
public static CollectionContents GetCollectionContent(CollectionItem collectionItem, string userid) {
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
// get age ratings for specified user
List<AgeGroups.AgeRestrictionGroupings> UserAgeGroupings = new List<AgeGroups.AgeRestrictionGroupings>();
bool UserAgeGroupIncludeUnrated = true;
if (userid != "")
{
Authentication.UserTable<Authentication.ApplicationUser> userTable = new UserTable<ApplicationUser>(db);
var user = userTable.GetUserById(userid);
if (user.SecurityProfile.AgeRestrictionPolicy.IncludeUnrated == false)
{
UserAgeGroupIncludeUnrated = false;
}
foreach (AgeGroups.AgeRestrictionGroupings ageGrouping in Enum.GetValues(typeof(AgeGroups.AgeRestrictionGroupings)))
{
if (ageGrouping <= user.SecurityProfile.AgeRestrictionPolicy.MaximumAgeRestriction && ageGrouping != AgeGroups.AgeRestrictionGroupings.Unclassified)
{
UserAgeGroupings.Add(ageGrouping);
}
}
}
List<CollectionContents.CollectionPlatformItem> collectionPlatformItems = new List<CollectionContents.CollectionPlatformItem>();
// get platforms
@@ -230,6 +273,10 @@ namespace gaseous_server.Classes
}
}
// age ratings
AgeGroups.AgeRestrictionGroupings AgeGrouping = AgeGroups.AgeRestrictionGroupings.Unclassified;
bool ContainsUnclassifiedAgeGroup = false;
// build collection
List<CollectionContents.CollectionPlatformItem> platformItems = new List<CollectionContents.CollectionPlatformItem>();
@@ -247,18 +294,29 @@ namespace gaseous_server.Classes
isDynamic = true;
}
List<Game> games = new List<Game>();
Controllers.v1_1.GamesController.GameReturnPackage games = new Controllers.v1_1.GamesController.GameReturnPackage();
if (isDynamic == true)
{
games = GamesController.GetGames("",
platform.Id.ToString(),
string.Join(",", collectionItem.Genres),
string.Join(",", collectionItem.Players),
string.Join(",", collectionItem.PlayerPerspectives),
string.Join(",", collectionItem.Themes),
collectionItem.MinimumRating,
collectionItem.MaximumRating
);
Controllers.v1_1.GamesController.GameSearchModel searchModel = new Controllers.v1_1.GamesController.GameSearchModel{
Name = "",
Platform = new List<string>{
platform.Id.ToString()
},
Genre = collectionItem.Genres.ConvertAll(s => s.ToString()),
GameMode = collectionItem.Players.ConvertAll(s => s.ToString()),
PlayerPerspective = collectionItem.PlayerPerspectives.ConvertAll(s => s.ToString()),
Theme = collectionItem.Themes.ConvertAll(s => s.ToString()),
GameRating = new Controllers.v1_1.GamesController.GameSearchModel.GameRatingItem{
MinimumRating = collectionItem.MinimumRating,
MaximumRating = collectionItem.MaximumRating
},
GameAgeRating = new Controllers.v1_1.GamesController.GameSearchModel.GameAgeRatingItem{
AgeGroupings = UserAgeGroupings,
IncludeUnrated = UserAgeGroupIncludeUnrated
}
};
games = Controllers.v1_1.GamesController.GetGames(searchModel, userid);
}
CollectionContents.CollectionPlatformItem collectionPlatformItem = new CollectionContents.CollectionPlatformItem(platform);
@@ -274,7 +332,7 @@ namespace gaseous_server.Classes
) && alwaysIncludeItem.PlatformId == platform.Id
)
{
Game AlwaysIncludeGame = Games.GetGame(alwaysIncludeItem.GameId, false, false, false);
MinimalGameItem AlwaysIncludeGame = new MinimalGameItem(Games.GetGame(alwaysIncludeItem.GameId, false, false, false));
CollectionContents.CollectionPlatformItem.CollectionGameItem gameItem = new CollectionContents.CollectionPlatformItem.CollectionGameItem(AlwaysIncludeGame);
gameItem.InclusionStatus = new CollectionItem.AlwaysIncludeItem();
gameItem.InclusionStatus.PlatformId = alwaysIncludeItem.PlatformId;
@@ -286,7 +344,7 @@ namespace gaseous_server.Classes
}
}
foreach (Game game in games) {
foreach (MinimalGameItem game in games.Games) {
bool gameAlreadyInList = false;
foreach (CollectionContents.CollectionPlatformItem.CollectionGameItem existingGame in collectionPlatformItem.Games)
{
@@ -341,6 +399,17 @@ namespace gaseous_server.Classes
}
}
}
// handle age grouping
AgeGroups.AgeRestrictionGroupings CurrentAgeGroup = AgeGroups.GetAgeGroupFromAgeRatings(game.AgeRatings);
if (CurrentAgeGroup > AgeGrouping)
{
AgeGrouping = CurrentAgeGroup;
}
if (CurrentAgeGroup == AgeGroups.AgeRestrictionGroupings.Unclassified)
{
ContainsUnclassifiedAgeGroup = true;
}
}
collectionPlatformItem.Games.Sort((x, y) => x.Name.CompareTo(y.Name));
@@ -369,29 +438,39 @@ namespace gaseous_server.Classes
collectionPlatformItems.Sort((x, y) => x.Name.CompareTo(y.Name));
CollectionContents collectionContents = new CollectionContents();
collectionContents.Collection = collectionPlatformItems;
CollectionContents collectionContents = new CollectionContents
{
Collection = collectionPlatformItems,
AgeGroup = AgeGrouping,
ContainsUnclassifiedAgeGroup = ContainsUnclassifiedAgeGroup
};
return collectionContents;
}
public static void CompileCollections(long CollectionId)
public static void CompileCollections(long CollectionId, string userid)
{
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
CollectionItem collectionItem = GetCollection(CollectionId);
CollectionItem collectionItem = GetCollection(CollectionId, userid);
if (collectionItem.BuildStatus == CollectionItem.CollectionBuildStatus.WaitingForBuild)
{
Logging.Log(Logging.LogType.Information, "Collections", "Beginning build of collection: " + collectionItem.Name);
CollectionContents collectionContents = GetCollectionContent(collectionItem, userid);
// set starting
string sql = "UPDATE RomCollections SET BuiltStatus=@bs WHERE Id=@id";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", collectionItem.Id);
dbDict.Add("bs", CollectionItem.CollectionBuildStatus.Building);
string sql = "UPDATE RomCollections SET BuiltStatus=@bs, AgeGroup=@ag, AgeGroupUnclassified=@agu WHERE Id=@id";
Dictionary<string, object> dbDict = new Dictionary<string, object>
{
{ "id", collectionItem.Id },
{ "bs", CollectionItem.CollectionBuildStatus.Building },
{ "ag", collectionContents.AgeGroup },
{ "agu", collectionContents.ContainsUnclassifiedAgeGroup }
};
db.ExecuteCMD(sql, dbDict);
List<CollectionContents.CollectionPlatformItem> collectionPlatformItems = GetCollectionContent(collectionItem).Collection;
List<CollectionContents.CollectionPlatformItem> collectionPlatformItems = collectionContents.Collection;
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, collectionItem.Id + collectionItem.ArchiveExtension);
string ZipFileTempPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, collectionItem.Id.ToString());
@@ -758,6 +837,9 @@ namespace gaseous_server.Classes
}
}
public AgeGroups.AgeRestrictionGroupings AgeGroup { get; set; }
public bool ContainsUnclassifiedAgeGroup { get; set; }
public class CollectionPlatformItem {
public CollectionPlatformItem(IGDB.Models.Platform platform) {
string[] PropertyWhitelist = new string[] { "Id", "Name", "Slug" };
@@ -808,49 +890,44 @@ namespace gaseous_server.Classes
}
}
public class CollectionGameItem {
public CollectionGameItem(IGDB.Models.Game game) {
string[] PropertyWhitelist = new string[] { "Id", "Name", "Slug", "Cover" };
PropertyInfo[] srcProperties = typeof(IGDB.Models.Game).GetProperties();
PropertyInfo[] dstProperties = typeof(CollectionPlatformItem.CollectionGameItem).GetProperties();
foreach (PropertyInfo srcProperty in srcProperties) {
if (PropertyWhitelist.Contains<string>(srcProperty.Name))
public class CollectionGameItem : MinimalGameItem
{
foreach (PropertyInfo dstProperty in dstProperties)
public CollectionGameItem(MinimalGameItem gameObject)
{
if (srcProperty.Name == dstProperty.Name)
{
if (srcProperty.GetValue(game) != null) {
string compareName = srcProperty.PropertyType.Name.ToLower().Split("`")[0];
switch(compareName) {
case "identityorvalue":
string newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(srcProperty.GetValue(game));
Dictionary<string, object> newDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(newObjectValue);
dstProperty.SetValue(this, newDict["Id"]);
break;
default:
dstProperty.SetValue(this, srcProperty.GetValue(game));
break;
}
}
}
}
}
}
this.Id = gameObject.Id;
this.Name = gameObject.Name;
this.Slug = gameObject.Slug;
this.TotalRating = gameObject.TotalRating;
this.TotalRatingCount = gameObject.TotalRatingCount;
this.Cover = gameObject.Cover;
this.Artworks = gameObject.Artworks;
this.FirstReleaseDate = gameObject.FirstReleaseDate;
this.AgeRatings = gameObject.AgeRatings;
}
public long Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public long Cover { get; set;}
public IGDB.Models.Cover CoverItem
public IGDB.Models.Cover? CoverItem
{
get
{
IGDB.Models.Cover cover = Covers.GetCover(Cover, Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory, "Games", Slug), false);
if (Cover != null)
{
IGDB.Models.Cover cover = Covers.GetCover(Cover.Id, Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory, "Games", Slug), false);
return cover;
}
else
{
return null;
}
}
}
public AgeGroups.AgeRestrictionGroupings AgeGrouping
{
get
{
return AgeGroups.GetAgeGroupFromAgeRatings(this.AgeRatings);
}
}
public CollectionItem.AlwaysIncludeItem InclusionStatus { get; set; }

View File

@@ -72,32 +72,7 @@ namespace gaseous_server.Classes.Metadata
}
// compile the ratings values into the ratings groups
AgeRestrictionGroupings highestAgeGroup = AgeRestrictionGroupings.Unclassified;
foreach (AgeRating ageRating in ageRatings)
{
foreach (KeyValuePair<AgeRestrictionGroupings, AgeGroupItem> ageGroupItem in AgeGroupingsFlat)
{
PropertyInfo[] groupProps = typeof(AgeGroupItem).GetProperties();
foreach (PropertyInfo property in groupProps)
{
if (RatingsBoards.Contains(property.Name))
{
List<AgeRatingTitle> ratingBoard = (List<AgeRatingTitle>)property.GetValue(ageGroupItem.Value);
foreach (AgeRatingTitle ratingTitle in ratingBoard)
{
if (ageRating.Rating == ratingTitle)
{
if (highestAgeGroup < ageGroupItem.Key)
{
highestAgeGroup = ageGroupItem.Key;
}
}
}
}
}
}
}
AgeRestrictionGroupings highestAgeGroup = GetAgeGroupFromAgeRatings(ageRatings);
// return the compiled ratings group
AgeGroup ageGroup = new AgeGroup();
@@ -138,6 +113,39 @@ namespace gaseous_server.Classes.Metadata
return null;
}
public static AgeRestrictionGroupings GetAgeGroupFromAgeRatings(List<AgeRating> ageRatings)
{
// compile the ratings values into the ratings groups
AgeRestrictionGroupings highestAgeGroup = AgeRestrictionGroupings.Unclassified;
foreach (AgeRating ageRating in ageRatings)
{
foreach (KeyValuePair<AgeRestrictionGroupings, AgeGroupItem> ageGroupItem in AgeGroupingsFlat)
{
PropertyInfo[] groupProps = typeof(AgeGroupItem).GetProperties();
foreach (PropertyInfo property in groupProps)
{
if (RatingsBoards.Contains(property.Name))
{
List<AgeRatingTitle> ratingBoard = (List<AgeRatingTitle>)property.GetValue(ageGroupItem.Value);
foreach (AgeRatingTitle ratingTitle in ratingBoard)
{
if (ageRating.Rating == ratingTitle)
{
if (highestAgeGroup < ageGroupItem.Key)
{
highestAgeGroup = ageGroupItem.Key;
}
}
}
}
}
}
}
return highestAgeGroup;
}
public class AgeGroup
{
public long? Id { get; set; }

View File

@@ -538,6 +538,7 @@ namespace gaseous_server.Classes.Metadata
{
this.Id = gameObject.Id;
this.Name = gameObject.Name;
this.Slug = gameObject.Slug;
this.TotalRating = gameObject.TotalRating;
this.TotalRatingCount = gameObject.TotalRatingCount;
this.Cover = gameObject.Cover;
@@ -561,6 +562,7 @@ namespace gaseous_server.Classes.Metadata
public long? Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public double? TotalRating { get; set; }
public int? TotalRatingCount { get; set; }
public bool HasSavedGame { get; set; } = false;

View File

@@ -3,8 +3,10 @@ using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using Authentication;
using gaseous_server.Classes;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace gaseous_server.Controllers
@@ -16,6 +18,17 @@ namespace gaseous_server.Controllers
[Authorize]
public class CollectionsController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
public CollectionsController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
/// <summary>
/// Gets all ROM collections
/// </summary>
@@ -24,9 +37,16 @@ namespace gaseous_server.Controllers
[MapToApiVersion("1.1")]
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
public List<Classes.Collections.CollectionItem> GetCollections()
public async Task<ActionResult> GetCollectionsAsync()
{
return Classes.Collections.GetCollections();
var user = await _userManager.GetUserAsync(User);
if (user != null)
{
return Ok(Classes.Collections.GetCollections(user.Id));
}
return NotFound();
}
/// <summary>
@@ -41,22 +61,31 @@ namespace gaseous_server.Controllers
[Route("{CollectionId}")]
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GetCollection(long CollectionId, bool Build = false)
public async Task<ActionResult> GetCollection(long CollectionId, bool Build = false)
{
var user = await _userManager.GetUserAsync(User);
if (user != null)
{
try
{
if (Build == true)
{
Classes.Collections.StartCollectionItemBuild(CollectionId);
Classes.Collections.StartCollectionItemBuild(CollectionId, user.Id);
}
return Ok(Classes.Collections.GetCollection(CollectionId));
return Ok(Classes.Collections.GetCollection(CollectionId, user.Id));
}
catch
{
return NotFound();
}
}
else
{
return NotFound();
}
}
/// <summary>
/// Gets the contents of the specified ROM collection
@@ -69,18 +98,27 @@ namespace gaseous_server.Controllers
[Route("{CollectionId}/Roms")]
[ProducesResponseType(typeof(List<Classes.Collections.CollectionContents.CollectionPlatformItem>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GetCollectionRoms(long CollectionId)
public async Task<ActionResult> GetCollectionRoms(long CollectionId)
{
var user = await _userManager.GetUserAsync(User);
if (user != null)
{
try
{
Classes.Collections.CollectionItem collectionItem = Classes.Collections.GetCollection(CollectionId);
return Ok(Classes.Collections.GetCollectionContent(collectionItem));
Classes.Collections.CollectionItem collectionItem = Classes.Collections.GetCollection(CollectionId, user.Id);
return Ok(Classes.Collections.GetCollectionContent(collectionItem, user.Id));
}
catch
{
return NotFound();
}
}
else
{
return NotFound();
}
}
/// <summary>
/// Gets a preview of the provided collection item
@@ -94,17 +132,26 @@ namespace gaseous_server.Controllers
[Authorize(Roles = "Admin,Gamer")]
[ProducesResponseType(typeof(List<Classes.Collections.CollectionContents.CollectionPlatformItem>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GetCollectionRomsPreview(Classes.Collections.CollectionItem Item)
public async Task<ActionResult> GetCollectionRomsPreview(Classes.Collections.CollectionItem Item)
{
var user = await _userManager.GetUserAsync(User);
if (user != null)
{
try
{
return Ok(Classes.Collections.GetCollectionContent(Item));
return Ok(Classes.Collections.GetCollectionContent(Item, user.Id));
}
catch (Exception ex)
{
return NotFound(ex);
}
}
else
{
return NotFound();
}
}
/// <summary>
/// Gets ROM collection in zip format
@@ -117,11 +164,15 @@ namespace gaseous_server.Controllers
[Route("{CollectionId}/Roms/Zip")]
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GetCollectionRomsZip(long CollectionId)
public async Task<ActionResult> GetCollectionRomsZip(long CollectionId)
{
var user = await _userManager.GetUserAsync(User);
if (user != null)
{
try
{
Classes.Collections.CollectionItem collectionItem = Classes.Collections.GetCollection(CollectionId);
Classes.Collections.CollectionItem collectionItem = Classes.Collections.GetCollection(CollectionId, user.Id);
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, CollectionId + ".zip");
@@ -140,6 +191,11 @@ namespace gaseous_server.Controllers
return NotFound();
}
}
else
{
return NotFound();
}
}
/// <summary>
/// Creates a new ROM collection
@@ -152,17 +208,26 @@ namespace gaseous_server.Controllers
[Authorize(Roles = "Admin,Gamer")]
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult NewCollection(Classes.Collections.CollectionItem Item)
public async Task<ActionResult> NewCollectionAsync(Classes.Collections.CollectionItem Item)
{
var user = await _userManager.GetUserAsync(User);
if (user != null)
{
try
{
return Ok(Classes.Collections.NewCollection(Item));
return Ok(Classes.Collections.NewCollection(Item, user.Id));
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
else
{
return NotFound();
}
}
/// <summary>
/// Edits an existing collection
@@ -177,17 +242,26 @@ namespace gaseous_server.Controllers
[Authorize(Roles = "Admin,Gamer")]
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult EditCollection(long CollectionId, Classes.Collections.CollectionItem Item)
public async Task<ActionResult> EditCollection(long CollectionId, Classes.Collections.CollectionItem Item)
{
var user = await _userManager.GetUserAsync(User);
if (user != null)
{
try
{
return Ok(Classes.Collections.EditCollection(CollectionId, Item, true));
return Ok(Classes.Collections.EditCollection(CollectionId, Item, user.Id, true));
}
catch
{
return NotFound();
}
}
else
{
return NotFound();
}
}
/// <summary>
/// Edits an existing collection
@@ -202,11 +276,15 @@ namespace gaseous_server.Controllers
[Route("{CollectionId}/AlwaysInclude")]
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult EditCollectionAlwaysInclude(long CollectionId, [FromQuery]bool Rebuild, [FromBody]Collections.CollectionItem.AlwaysIncludeItem Inclusion)
public async Task<ActionResult> EditCollectionAlwaysInclude(long CollectionId, [FromQuery]bool Rebuild, [FromBody]Collections.CollectionItem.AlwaysIncludeItem Inclusion)
{
var user = await _userManager.GetUserAsync(User);
if (user != null)
{
try
{
Collections.CollectionItem collectionItem = Classes.Collections.GetCollection(CollectionId);
Collections.CollectionItem collectionItem = Classes.Collections.GetCollection(CollectionId, user.Id);
bool ItemFound = false;
foreach (Collections.CollectionItem.AlwaysIncludeItem includeItem in collectionItem.AlwaysInclude)
{
@@ -220,13 +298,18 @@ namespace gaseous_server.Controllers
collectionItem.AlwaysInclude.Add(Inclusion);
}
return Ok(Classes.Collections.EditCollection(CollectionId, collectionItem, Rebuild));
return Ok(Classes.Collections.EditCollection(CollectionId, collectionItem, user.Id, Rebuild));
}
catch
{
return NotFound();
}
}
else
{
return NotFound();
}
}
/// <summary>
/// Deletes the specified ROM collection
@@ -239,11 +322,15 @@ namespace gaseous_server.Controllers
[Route("{CollectionId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult DeleteCollection(long CollectionId)
public async Task<ActionResult> DeleteCollection(long CollectionId)
{
var user = await _userManager.GetUserAsync(User);
if (user != null)
{
try
{
Classes.Collections.DeleteCollection(CollectionId);
Classes.Collections.DeleteCollection(CollectionId, user.Id);
return Ok();
}
catch
@@ -251,5 +338,10 @@ namespace gaseous_server.Controllers
return NotFound();
}
}
else
{
return NotFound();
}
}
}
}

View File

@@ -474,6 +474,7 @@ SELECT DISTINCT
Game.Id,
Game.`Name`,
Game.NameThe,
Game.Slug,
Game.PlatformId,
Game.TotalRating,
Game.TotalRatingCount,
@@ -542,11 +543,14 @@ FROM
// compile data for return
int pageOffset = pageSize * (pageNumber - 1);
for (int i = pageOffset; i < dbResponse.Rows.Count; i++)
{
if (pageNumber != 0 && pageSize != 0)
{
if (i >= (pageOffset + pageSize))
{
break;
}
}
Game retGame = Storage.BuildCacheObject<Game>(new Game() , dbResponse.Rows[i]);
Games.MinimalGameItem retMinGame = new Games.MinimalGameItem(retGame);

View File

@@ -334,7 +334,8 @@ namespace gaseous_server
case QueueItemType.CollectionCompiler:
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Collection Compiler");
Classes.Collections.CompileCollections((long)Options);
Dictionary<string, object> collectionOptions = (Dictionary<string, object>)Options;
Classes.Collections.CompileCollections((long)collectionOptions["Id"], (string)collectionOptions["UserId"]);
break;
case QueueItemType.MediaGroupCompiler:

View File

@@ -0,0 +1,4 @@
ALTER TABLE `RomCollections`
ADD COLUMN `OwnedBy` VARCHAR(45) NULL,
ADD COLUMN `AgeGroup` INT NULL,
ADD COLUMN `AgeGroupUnclassified` BOOLEAN NULL;

View File

@@ -61,6 +61,7 @@
<None Remove="Support\Database\MySQL\gaseous-1014.sql" />
<None Remove="Support\Database\MySQL\gaseous-1015.sql" />
<None Remove="Support\Database\MySQL\gaseous-1016.sql" />
<None Remove="Support\Database\MySQL\gaseous-1017.sql" />
<None Remove="Classes\Metadata\" />
</ItemGroup>
<ItemGroup>
@@ -99,5 +100,6 @@
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1014.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1015.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1016.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1017.sql" />
</ItemGroup>
</Project>

View File

@@ -59,7 +59,7 @@
<tr>
<th>Directory Layout</th>
<td>
<select id="collection_directorylayout" style="width: 100%;" onchange="DisplayDirectoryLabel();">
<select id="collection_directorylayout" style="width: 100%;" data-minimum-results-for-search="Infinity" onchange="DisplayDirectoryLabel();">
<option id="collection_directorylayout_gaseous" selected="selected" value="Gaseous">Standard</option>
<option id="collection_directorylayout_retropie" value="RetroPie">RetroPie</option>
</select>
@@ -85,7 +85,7 @@
Include BIOS files (if available)
</th>
<td>
<select id="collection_includebios" style="width: 100%;">
<select id="collection_includebios" style="width: 100%;" data-minimum-results-for-search="Infinity">
<option id="collection_includebios_yes" selected="selected" value="true">Yes</option>
<option id="collection_includebios_no" value="false">No</option>
</select>
@@ -589,11 +589,11 @@
gameCoverCell.className = 'collections_preview_gamecovercell';
var gameImage = document.createElement('img');
gameImage.className = 'game_tile_image game_tile_image_small';
if (gameItem.cover) {
gameImage.src = '/api/v1.1/Games/' + gameItem.id + '/cover/image/cover_small/' + gameItem.coverItem.imageId + '.jpg';
} else {
gameImage.className = 'game_tile_image game_tile_image_small lazy';
gameImage.src = '/images/unknowngame.png';
if (gameItem.cover) {
gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameItem.id + '/cover/image/cover_small/' + gameItem.coverItem.imageId + '.jpg');
} else {
gameImage.className = 'game_tile_image game_tile_image_small unknown';
}
gameCoverCell.appendChild(gameImage);
@@ -626,6 +626,13 @@
var collectionSize = document.getElementById('collectionedit_previewbox_size');
collectionSize.innerHTML = "Estimated uncompressed collection size: " + formatBytes(data.collectionProjectedSizeBytes);
}
$('#collectionedit_previewbox .lazy').Lazy({
scrollDirection: 'vertical',
effect: 'fadeIn',
visibleOnly: true,
appendScroll: $('#collectionedit_previewbox')
});
}
function DisplayFormattedBytes(inputElement, labelElement) {