Merge branch 'main' into more-slot-categories

This commit is contained in:
LumaLivy 2021-12-14 13:46:17 -05:00
commit eb865592b9
172 changed files with 10476 additions and 643 deletions

16
.gitignore vendored
View file

@ -1,3 +1,9 @@
# LBP resources.
r/
# rider
.idea/
r/ # cdn resources folder
bin/
obj/
@ -12,8 +18,14 @@ riderModule.iml
/ProjectLighthouse/logs/*
/ProjectLighthouse/ProjectLighthouse.csproj.user
.vs/
.vscode/
.editorconfig
lighthouse.config.json
gitBranch.txt
gitVersion.txt
ProjectLighthouse/.vscode/tasks.json
ProjectLighthouse/.vscode/launch.json
logs/Startup.log
logs/LoggerInfo.log
logs/all.log
.vscode/tasks.json
.vscode/launch.json
.editorconfig

View file

@ -4,9 +4,16 @@
<data-source source="LOCAL" name="lighthouse@localhost" uuid="3bfb85d6-6cc2-427d-9288-06e05ab58c10">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-driver>com.mysql.cj.jdbc.NonRegisteringDriver</jdbc-driver>
<jdbc-url>jdbc:mysql://localhost:3306/lighthouse</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
<data-source source="LOCAL" name="Lighthouse Production" uuid="b323608d-d984-40d0-942e-2c2ea35006d8">
<driver-ref>mariadb</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mariadb://localhost:3306</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="PROJECT" libraries="{fomantic-ui, sha256}" />
</component>
</project>

View file

@ -9,6 +9,7 @@ using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Tests
{
@ -25,9 +26,15 @@ namespace LBPUnion.ProjectLighthouse.Tests
this.Client = this.Server.CreateClient();
}
public async Task<HttpResponseMessage> AuthenticateResponse(int number = 0)
public async Task<HttpResponseMessage> AuthenticateResponse(int number = 0, bool createUser = true)
{
const string username = "unitTestUser";
if (createUser)
{
await using Database database = new();
if (await database.Users.FirstOrDefaultAsync(u => u.Username == $"{username}{number}") == null)
await database.CreateUser($"{username}{number}", HashHelper.BCryptHash($"unitTestPassword{number}"));
}
string stringContent = $"{LoginData.UsernamePrefix}{username}{number}{(char)0x00}";

View file

@ -49,11 +49,10 @@ namespace LBPUnion.ProjectLighthouse.Tests
{
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/announce", loginResult.AuthTicket);
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/enterLevel/1", loginResult.AuthTicket);
string responseContent = await response.Content.ReadAsStringAsync();
Assert.True(response.IsSuccessStatusCode);
Assert.Contains("You are now logged in", responseContent);
Assert.False(response.StatusCode == HttpStatusCode.Forbidden);
}
[DatabaseFact]

View file

@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types;
namespace LBPUnion.ProjectLighthouse.Tests
@ -12,8 +13,8 @@ namespace LBPUnion.ProjectLighthouse.Tests
await using Database database = new();
int rand = new Random().Next();
User userA = await database.CreateUser("createUserTwiceTest" + rand);
User userB = await database.CreateUser("createUserTwiceTest" + rand);
User userA = await database.CreateUser("createUserTwiceTest" + rand, HashHelper.GenerateAuthToken());
User userB = await database.CreateUser("createUserTwiceTest" + rand, HashHelper.GenerateAuthToken());
database.Users.Remove(userA);
database.Users.Remove(userB);

View file

@ -3,6 +3,7 @@ using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types;
using Xunit;
@ -36,7 +37,6 @@ namespace LBPUnion.ProjectLighthouse.Tests
semaphore.Release();
Assert.True(result.IsSuccessStatusCode);
}
public async Task<int> GetPlayerCount() => Convert.ToInt32(await this.Client.GetStringAsync("LITTLEBIGPLANETPS3_XML/totalPlayerCount"));
[DatabaseFact]
public async Task ShouldIncrementPlayerCount()
@ -45,14 +45,14 @@ namespace LBPUnion.ProjectLighthouse.Tests
await semaphore.WaitAsync();
int oldPlayerCount = await this.GetPlayerCount();
int oldPlayerCount = await StatisticsHelper.RecentMatches();
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest
("LITTLEBIGPLANETPS3_XML/match", Encoding.ASCII.GetBytes("[UpdateMyPlayerData,[\"Player\":\"1984\"]]"), loginResult.AuthTicket);
Assert.True(result.IsSuccessStatusCode);
int playerCount = await this.GetPlayerCount();
int playerCount = await StatisticsHelper.RecentMatches();
semaphore.Release();
Assert.Equal(oldPlayerCount + 1, playerCount);

View file

@ -1,5 +1,6 @@
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Levels;
using LBPUnion.ProjectLighthouse.Types.Profiles;
@ -14,8 +15,8 @@ namespace LBPUnion.ProjectLighthouse.Tests
{
await using Database database = new();
User userA = await database.CreateUser("unitTestUser0");
User userB = await database.CreateUser("unitTestUser1");
User userA = await database.CreateUser("unitTestUser0", HashHelper.GenerateAuthToken());
User userB = await database.CreateUser("unitTestUser1", HashHelper.GenerateAuthToken());
Location l = new()
{

View file

@ -78,7 +78,9 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MM/@EntryIndexedValue">MM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NAT/@EntryIndexedValue">NAT</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NP/@EntryIndexedValue">NP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PS/@EntryIndexedValue">PS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PSP/@EntryIndexedValue">PSP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RPCS/@EntryIndexedValue">RPCS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Method/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
@ -126,5 +128,6 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCUS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unfavourite/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unheart/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unpublish/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=yourthumb/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View file

@ -47,7 +47,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
XmlSerializer serializer = new(typeof(Comment));
Comment? comment = (Comment?)serializer.Deserialize(new StringReader(bodyString));
User? poster = await this.database.UserFromRequest(this.Request);
User? poster = await this.database.UserFromGameRequest(this.Request);
if (poster == null) return this.StatusCode(403, "");
User? target = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
@ -66,14 +66,11 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("deleteUserComment/{username}")]
public async Task<IActionResult> DeleteComment([FromQuery] int commentId, string username)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
Comment? comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId);
if (comment == null)
{
return this.NotFound();
}
if (comment == null) return this.NotFound();
if (comment.TargetUserId != user.UserId && comment.PosterUserId != user.UserId) return this.StatusCode(403, "");

View file

@ -24,13 +24,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("play/user/{slotId}")]
public async Task<IActionResult> PlayLevel(int slotId)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slotId);
if (slot == null) return this.StatusCode(403, "");
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
GameVersion gameVersion = token.GameVersion;
@ -62,7 +62,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
{
v = await visited.FirstOrDefaultAsync();
}
if (v == null) return this.NotFound();
switch (gameVersion)
@ -94,7 +94,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpGet("enterLevel/{id:int}")]
public async Task<IActionResult> EnterLevel(int id)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);

View file

@ -26,7 +26,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("npdata")]
public async Task<IActionResult> NPData()
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
this.Request.Body.Position = 0;
@ -69,18 +69,16 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpGet("myFriends")]
public async Task<IActionResult> MyFriends()
{
(User, Token)? userAndToken = await this.database.UserAndTokenFromRequest(this.Request);
(User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request);
if (userAndToken == null) return this.StatusCode(403, "");
// ReSharper disable once PossibleInvalidOperationException
User user = userAndToken.Value.Item1;
Token token = userAndToken.Value.Item2;
GameToken gameToken = userAndToken.Value.Item2;
if (!FriendHelper.FriendIdsByUserId.TryGetValue(user.UserId, out int[]? friendIds) || friendIds == null)
{
return this.Ok(LbpSerializer.BlankElement("myFriends"));
}
string friends = "";
foreach (int friendId in friendIds)
@ -88,7 +86,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
User? friend = await this.database.Users.Include(u => u.Location).FirstOrDefaultAsync(u => u.UserId == friendId);
if (friend == null) continue;
friends += friend.Serialize(token.GameVersion);
friends += friend.Serialize(gameToken.GameVersion);
}
return this.Ok(LbpSerializer.StringElement("myFriends", friends));

View file

@ -29,7 +29,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpGet("slots/lolcatftw/{username}")]
public async Task<IActionResult> GetLevelQueue(string username, [FromQuery] int pageSize, [FromQuery] int pageStart)
{
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
GameVersion gameVersion = token.GameVersion;
@ -56,22 +56,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("lolcatftw/add/user/{id:int}")]
public async Task<IActionResult> AddQueuedLevel(int id)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
QueuedLevel? queuedLevel = await this.database.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
if (queuedLevel != null) return this.Ok();
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.NotFound();
this.database.QueuedLevels.Add
(
new QueuedLevel
{
SlotId = id,
UserId = user.UserId,
}
);
await this.database.SaveChangesAsync();
await this.database.QueueLevel(user, slot);
return this.Ok();
}
@ -79,13 +70,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("lolcatftw/remove/user/{id:int}")]
public async Task<IActionResult> RemoveQueuedLevel(int id)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
QueuedLevel? queuedLevel = await this.database.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
if (queuedLevel != null) this.database.QueuedLevels.Remove(queuedLevel);
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.NotFound();
await this.database.SaveChangesAsync();
await this.database.UnqueueLevel(user, slot);
return this.Ok();
}
@ -93,7 +84,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("lolcatftw/clear")]
public async Task<IActionResult> ClearQueuedLevels()
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
this.database.QueuedLevels.RemoveRange(this.database.QueuedLevels.Where(q => q.UserId == user.UserId));
@ -110,7 +101,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpGet("favouriteSlots/{username}")]
public async Task<IActionResult> GetFavouriteSlots(string username, [FromQuery] int pageSize, [FromQuery] int pageStart)
{
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
GameVersion gameVersion = token.GameVersion;
@ -137,22 +128,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("favourite/slot/user/{id:int}")]
public async Task<IActionResult> AddFavouriteSlot(int id)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
HeartedLevel? heartedLevel = await this.database.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
if (heartedLevel != null) return this.Ok();
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.NotFound();
this.database.HeartedLevels.Add
(
new HeartedLevel
{
SlotId = id,
UserId = user.UserId,
}
);
await this.database.SaveChangesAsync();
await this.database.HeartLevel(user, slot);
return this.Ok();
}
@ -160,13 +142,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("unfavourite/slot/user/{id:int}")]
public async Task<IActionResult> RemoveFavouriteSlot(int id)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
HeartedLevel? heartedLevel = await this.database.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
if (heartedLevel != null) this.database.HeartedLevels.Remove(heartedLevel);
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.NotFound();
await this.database.SaveChangesAsync();
await this.database.UnheartLevel(user, slot);
return this.Ok();
}
@ -180,7 +162,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpGet("favouriteUsers/{username}")]
public async Task<IActionResult> GetFavouriteUsers(string username, [FromQuery] int pageSize, [FromQuery] int pageStart)
{
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
IEnumerable<HeartedProfile> heartedProfiles = this.database.HeartedProfiles.Include
@ -204,26 +186,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("favourite/user/{username}")]
public async Task<IActionResult> AddFavouriteUser(string username)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
User? heartedUser = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
if (heartedUser == null) return this.NotFound();
HeartedProfile? heartedProfile = await this.database.HeartedProfiles.FirstOrDefaultAsync
(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
if (heartedProfile != null) return this.Ok();
this.database.HeartedProfiles.Add
(
new HeartedProfile
{
HeartedUserId = heartedUser.UserId,
UserId = user.UserId,
}
);
await this.database.SaveChangesAsync();
await this.database.HeartUser(user, heartedUser);
return this.Ok();
}
@ -231,17 +200,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("unfavourite/user/{username}")]
public async Task<IActionResult> RemoveFavouriteUser(string username)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
User? heartedUser = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
if (heartedUser == null) return this.NotFound();
HeartedProfile? heartedProfile = await this.database.HeartedProfiles.FirstOrDefaultAsync
(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
if (heartedProfile != null) this.database.HeartedProfiles.Remove(heartedProfile);
await this.database.SaveChangesAsync();
await this.database.UnheartUser(user, heartedUser);
return this.Ok();
}

View file

@ -1,5 +1,6 @@
#nullable enable
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Kettu;
@ -8,6 +9,7 @@ using LBPUnion.ProjectLighthouse.Logging;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Settings;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Controllers
{
@ -46,19 +48,48 @@ namespace LBPUnion.ProjectLighthouse.Controllers
string userLocation = ipAddress.ToString();
Token? token = await this.database.AuthenticateUser(loginData, userLocation, titleId);
GameToken? token = await this.database.AuthenticateUser(loginData, userLocation, titleId);
if (token == null) return this.StatusCode(403, "");
User? user = await this.database.UserFromToken(token);
User? user = await this.database.UserFromGameToken(token, true);
if (user == null) return this.StatusCode(403, "");
if (ServerSettings.Instance.UseExternalAuth)
{
string ipAddressAndName = $"{token.UserLocation}|{user.Username}";
if (DeniedAuthenticationHelper.RecentlyDenied(ipAddressAndName) || DeniedAuthenticationHelper.GetAttempts(ipAddressAndName) > 3)
{
this.database.AuthenticationAttempts.RemoveRange
(this.database.AuthenticationAttempts.Include(a => a.GameToken).Where(a => a.GameToken.UserId == user.UserId));
DeniedAuthenticationHelper.AddAttempt(ipAddressAndName);
await this.database.SaveChangesAsync();
return this.StatusCode(403, "");
}
AuthenticationAttempt authAttempt = new()
{
GameToken = token,
GameTokenId = token.TokenId,
Timestamp = TimestampHelper.Timestamp,
IPAddress = userLocation,
Platform = token.GameVersion == GameVersion.LittleBigPlanetVita ? Platform.Vita : Platform.PS3, // TODO: properly identify RPCS3
};
this.database.AuthenticationAttempts.Add(authAttempt);
}
else
{
token.Approved = true;
}
await this.database.SaveChangesAsync();
Logger.Log($"Successfully logged in user {user.Username} as {token.GameVersion} client ({titleId})", LoggerLevelLogin.Instance);
// Create a new room on LBP2+/Vita
if (token.GameVersion != GameVersion.LittleBigPlanet1)
{
RoomHelper.CreateRoom(user);
}
if (token.GameVersion != GameVersion.LittleBigPlanet1) RoomHelper.CreateRoom(user);
return this.Ok
(

View file

@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Kettu;
@ -10,7 +9,6 @@ using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Logging;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Match;
using LBPUnion.ProjectLighthouse.Types.Profiles;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@ -32,13 +30,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[Produces("text/plain")]
public async Task<IActionResult> Match()
{
(User, Token)? userAndToken = await this.database.UserAndTokenFromRequest(this.Request);
(User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request);
if (userAndToken == null) return this.StatusCode(403, "");
// ReSharper disable once PossibleInvalidOperationException
User user = userAndToken.Value.Item1;
Token token = userAndToken.Value.Item2;
GameToken gameToken = userAndToken.Value.Item2;
#region Parse match data
@ -72,51 +70,28 @@ namespace LBPUnion.ProjectLighthouse.Controllers
#endregion
#region Update LastMatch
LastMatch? lastMatch = await this.database.LastMatches.Where(l => l.UserId == user.UserId).FirstOrDefaultAsync();
// below makes it not look like trash
// ReSharper disable once ConvertIfStatementToNullCoalescingExpression
if (lastMatch == null)
{
lastMatch = new LastMatch
{
UserId = user.UserId,
};
this.database.LastMatches.Add(lastMatch);
}
lastMatch.Timestamp = TimestampHelper.Timestamp;
await this.database.SaveChangesAsync();
#endregion
await LastContactHelper.SetLastContact(user, gameToken.GameVersion);
#region Process match data
if (matchData is UpdateMyPlayerData playerData)
{
MatchHelper.SetUserLocation(user.UserId, token.UserLocation);
MatchHelper.SetUserLocation(user.UserId, gameToken.UserLocation);
Room? room = RoomHelper.FindRoomByUser(user, true);
if (playerData.RoomState != null)
{
if (room != null && Equals(room.Host, user)) room.State = (RoomState)playerData.RoomState;
}
if (room != null && Equals(room.Host, user))
room.State = (RoomState)playerData.RoomState;
}
if (matchData is FindBestRoom && MatchHelper.UserLocations.Count > 1)
{
FindBestRoomResponse? response = RoomHelper.FindBestRoom(user, token.UserLocation);
FindBestRoomResponse? response = RoomHelper.FindBestRoom(user, gameToken.UserLocation);
if (response == null) return this.NotFound();
string serialized = JsonSerializer.Serialize(response, typeof(FindBestRoomResponse));
foreach (Player player in response.Players)
{
MatchHelper.AddUserRecentlyDivedIn(user.UserId, player.User.UserId);
}
foreach (Player player in response.Players) MatchHelper.AddUserRecentlyDivedIn(user.UserId, player.User.UserId);
return this.Ok($"[{{\"StatusCode\":200}},{serialized}]");
}
@ -128,10 +103,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
{
User? player = await this.database.Users.FirstOrDefaultAsync(u => u.Username == playerUsername);
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
if (player != null)
{
users.Add(player);
}
if (player != null) users.Add(player);
else return this.BadRequest();
}

View file

@ -27,10 +27,20 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpGet("announce")]
public async Task<IActionResult> Announce()
{
User user = await this.database.UserFromRequest(this.Request);
User user = await this.database.UserFromGameRequest(this.Request, true);
if (user == null) return this.StatusCode(403, "");
return this.Ok($"You are now logged in as user {user.Username} (id {user.UserId}).\n\n" + ServerSettings.Instance.EulaText);
if (ServerSettings.Instance.UseExternalAuth)
return this.Ok
(
"Please stay on this screen.\n" +
$"Before continuing, you must approve this session at {ServerSettings.Instance.ExternalUrl}.\n" +
"Please keep in mind that if the session is denied you may have to wait up to 5-10 minutes to try logging in again.\n" +
"Once approved, you may press X and continue.\n\n" +
ServerSettings.Instance.EulaText
);
return this.Ok($"You are now logged in as {user.Username} (id: {user.UserId}).\n\n" + ServerSettings.Instance.EulaText);
}
[HttpGet("notification")]
@ -42,7 +52,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("filter")]
public async Task<IActionResult> Filter()
{
User user = await this.database.UserFromRequest(this.Request);
User user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
string loggedText = await new StreamReader(this.Request.Body).ReadToEndAsync();

View file

@ -9,6 +9,7 @@ using Kettu;
using LBPUnion.ProjectLighthouse.Logging;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Settings;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@ -29,9 +30,11 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("uploadPhoto")]
public async Task<IActionResult> UploadPhoto()
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
if (user.PhotosByMe >= ServerSettings.Instance.PhotosQuota) return this.BadRequest();
this.Request.Body.Position = 0;
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
@ -39,6 +42,14 @@ namespace LBPUnion.ProjectLighthouse.Controllers
Photo? photo = (Photo?)serializer.Deserialize(new StringReader(bodyString));
if (photo == null) return this.BadRequest();
foreach (Photo p in this.database.Photos.Where(p => p.CreatorId == user.UserId))
{
if (p.LargeHash == photo.LargeHash) return this.Ok(); // photo already uplaoded
if (p.MediumHash == photo.MediumHash) return this.Ok();
if (p.SmallHash == photo.SmallHash) return this.Ok();
if (p.PlanHash == photo.PlanHash) return this.Ok();
}
photo.CreatorId = user.UserId;
photo.Creator = user;
@ -103,10 +114,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers
if (userFromQuery == null) return this.NotFound();
List<Photo> photos = new();
foreach (Photo photo in this.database.Photos.Include(p => p.Creator))
{
photos.AddRange(photo.Subjects.Where(subject => subject.User.UserId == userFromQuery.UserId).Select(_ => photo));
}
foreach (Photo photo in this.database.Photos.Include
(p => p.Creator)) photos.AddRange(photo.Subjects.Where(subject => subject.User.UserId == userFromQuery.UserId).Select(_ => photo));
string response = photos.OrderByDescending
(s => s.Timestamp)
@ -120,7 +129,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("deletePhoto/{id:int}")]
public async Task<IActionResult> DeletePhoto(int id)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
Photo? photo = await this.database.Photos.FirstOrDefaultAsync(p => p.PhotoId == id);

View file

@ -9,6 +9,7 @@ using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Levels;
using LBPUnion.ProjectLighthouse.Types.Profiles;
using LBPUnion.ProjectLighthouse.Types.Settings;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@ -32,9 +33,11 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("startPublish")]
public async Task<IActionResult> StartPublish()
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
if (user.UsedSlots >= ServerSettings.Instance.EntitledSlots) return this.BadRequest();
Slot? slot = await this.GetSlotFromBody();
if (slot == null) return this.BadRequest(); // if the level cant be parsed then it obviously cant be uploaded
@ -65,17 +68,19 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("publish")]
public async Task<IActionResult> Publish()
{
// User user = await this.database.UserFromRequest(this.Request);
(User, Token)? userAndToken = await this.database.UserAndTokenFromRequest(this.Request);
// User user = await this.database.UserFromGameRequest(this.Request);
(User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request);
if (userAndToken == null) return this.StatusCode(403, "");
// ReSharper disable once PossibleInvalidOperationException
User user = userAndToken.Value.Item1;
Token token = userAndToken.Value.Item2;
GameToken gameToken = userAndToken.Value.Item2;
if (user.UsedSlots >= ServerSettings.Instance.EntitledSlots) return this.BadRequest();
Slot? slot = await this.GetSlotFromBody();
if (slot == null || slot.Location == null) return this.BadRequest();
if (slot?.Location == null) return this.BadRequest();
// Republish logic
if (slot.SlotId != 0)
@ -93,9 +98,35 @@ namespace LBPUnion.ProjectLighthouse.Controllers
slot.CreatorId = oldSlot.CreatorId;
slot.LocationId = oldSlot.LocationId;
slot.SlotId = oldSlot.SlotId;
slot.PlaysLBP1 = oldSlot.PlaysLBP1;
slot.PlaysLBP1Complete = oldSlot.PlaysLBP1Complete;
slot.PlaysLBP1Unique = oldSlot.PlaysLBP1Unique;
slot.PlaysLBP2 = oldSlot.PlaysLBP2;
slot.PlaysLBP2Complete = oldSlot.PlaysLBP2Complete;
slot.PlaysLBP2Unique = oldSlot.PlaysLBP2Unique;
slot.PlaysLBP3 = oldSlot.PlaysLBP3;
slot.PlaysLBP3Complete = oldSlot.PlaysLBP3Complete;
slot.PlaysLBP3Unique = oldSlot.PlaysLBP3Unique;
slot.PlaysLBPVita = oldSlot.PlaysLBPVita;
slot.PlaysLBPVitaComplete = oldSlot.PlaysLBPVitaComplete;
slot.PlaysLBPVitaUnique = oldSlot.PlaysLBPVitaUnique;
slot.FirstUploaded = oldSlot.FirstUploaded;
slot.LastUpdated = TimeHelper.UnixTimeMilliseconds();
slot.GameVersion = token.GameVersion;
slot.TeamPick = oldSlot.TeamPick;
slot.GameVersion = gameToken.GameVersion;
if (slot.MinimumPlayers == 0 || slot.MaximumPlayers == 0)
{
slot.MinimumPlayers = 1;
slot.MaximumPlayers = 4;
}
this.database.Entry(oldSlot).CurrentValues.SetValues(slot);
await this.database.SaveChangesAsync();
@ -114,7 +145,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
slot.CreatorId = user.UserId;
slot.FirstUploaded = TimeHelper.UnixTimeMilliseconds();
slot.LastUpdated = TimeHelper.UnixTimeMilliseconds();
slot.GameVersion = token.GameVersion;
slot.GameVersion = gameToken.GameVersion;
if (slot.MinimumPlayers == 0 || slot.MaximumPlayers == 0)
{
@ -131,7 +162,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("unpublish/{id:int}")]
public async Task<IActionResult> Unpublish(int id)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
Slot? slot = await this.database.Slots.Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == id);

View file

@ -14,8 +14,8 @@ using IOFile = System.IO.File;
namespace LBPUnion.ProjectLighthouse.Controllers
{
[ApiController]
[Route("LITTLEBIGPLANETPS3_XML/")]
[Produces("text/xml")]
[Route("LITTLEBIGPLANETPS3_XML")]
public class ResourcesController : ControllerBase
{
[HttpPost("showModerated")]
@ -39,6 +39,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers
return this.Ok(LbpSerializer.StringElement("resources", resources));
}
[ResponseCache(Duration = 86400)]
[HttpGet("/gameAssets/{hash}")]
[HttpGet("r/{hash}")]
public IActionResult GetResource(string hash)
{
@ -68,9 +70,14 @@ namespace LBPUnion.ProjectLighthouse.Controllers
return this.UnprocessableEntity();
}
if (HashHelper.Sha1Hash(file.Data) != hash)
string calculatedHash = HashHelper.Sha1Hash(file.Data).ToLower();
if (calculatedHash != hash)
{
Logger.Log($"File hash does not match the uploaded file! (hash: {hash}, type: {file.FileType})", LoggerLevelResources.Instance);
Logger.Log
(
$"File hash does not match the uploaded file! (hash: {hash}, calculatedHash: {calculatedHash}, type: {file.FileType})",
LoggerLevelResources.Instance
);
return this.Conflict();
}

View file

@ -1,10 +1,10 @@
#nullable enable
using System;
using System.IO;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types;
@ -31,7 +31,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("rate/user/{slotId}")]
public async Task<IActionResult> Rate(int slotId, [FromQuery] int rating)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
Slot? slot = await this.database.Slots.Include(s => s.Creator).Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == slotId);
@ -58,7 +58,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("dpadrate/user/{slotId:int}")]
public async Task<IActionResult> DPadRate(int slotId, [FromQuery] int rating)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
Slot? slot = await this.database.Slots.Include(s => s.Creator).Include(s => s.Location).FirstOrDefaultAsync(s => s.SlotId == slotId);
@ -76,32 +76,41 @@ namespace LBPUnion.ProjectLighthouse.Controllers
ratedLevel.Rating = Math.Max(Math.Min(1, rating), -1);
Review? review = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == slotId && r.ReviewerId == user.UserId);
if (review != null) review.Thumb = ratedLevel.Rating;
await this.database.SaveChangesAsync();
return this.Ok();
}
[HttpPost("postReview/user/{slotId:int}")]
public async Task<IActionResult> PostReview(int slotId) {
User? user = await this.database.UserFromRequest(this.Request);
public async Task<IActionResult> PostReview(int slotId)
{
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
Review? review = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == slotId && r.ReviewerId == user.UserId);
Review? newReview = await this.GetReviewFromBody();
if (newReview == null) return this.BadRequest();
if (review == null) {
review = new();
if (review == null)
{
review = new Review();
review.SlotId = slotId;
review.ReviewerId = user.UserId;
review.DeletedBy = "none";
review.DeletedBy = DeletedBy.None;
review.ThumbsUp = 0;
review.ThumbsDown = 0;
this.database.Reviews.Add(review);
}
review.Thumb = newReview.Thumb;
review.LabelCollection = newReview.LabelCollection;
review.Text = newReview.Text;
review.Deleted = false;
review.Timestamp = TimeHelper.UnixTimeMilliseconds();
// sometimes the game posts a review without also calling dpadrate/user/etc (why??)
// sometimes the game posts/updates a review rating without also calling dpadrate/user/etc (why??)
RatedLevel? ratedLevel = await this.database.RatedLevels.FirstOrDefaultAsync(r => r.SlotId == slotId && r.UserId == user.UserId);
if (ratedLevel == null)
{
@ -113,7 +122,6 @@ namespace LBPUnion.ProjectLighthouse.Controllers
}
ratedLevel.Rating = newReview.Thumb;
await this.database.SaveChangesAsync();
@ -121,94 +129,150 @@ namespace LBPUnion.ProjectLighthouse.Controllers
}
[HttpGet("reviewsFor/user/{slotId:int}")]
public async Task<IActionResult> ReviewsFor(int slotId, [FromQuery] int pageStart = 1, [FromQuery] int pageSize = 10)
public async Task<IActionResult> ReviewsFor(int slotId, [FromQuery] int pageStart = 1, [FromQuery] int pageSize = 10)
{
User? user = await this.database.UserFromRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
(User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request);
Token? token = await this.database.TokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
if (userAndToken == null) return this.StatusCode(403, "");
GameVersion gameVersion = token.GameVersion;
// ReSharper disable once PossibleInvalidOperationException
User user = userAndToken.Value.Item1;
GameToken gameToken = userAndToken.Value.Item2;
GameVersion gameVersion = gameToken.GameVersion;
Random rand = new();
IEnumerable<Review> reviews = this.database.Reviews.Where(r => r.SlotId == slotId && r.Slot.GameVersion <= gameVersion)
Review? yourReview = await this.database.Reviews.FirstOrDefaultAsync
(r => r.ReviewerId == user.UserId && r.SlotId == slotId && r.Slot.GameVersion <= gameVersion);
VisitedLevel? visitedLevel = await this.database.VisitedLevels.FirstOrDefaultAsync
(v => v.UserId == user.UserId && v.SlotId == slotId && v.Slot.GameVersion <= gameVersion);
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slotId);
if (slot == null) return this.BadRequest();
bool canNowReviewLevel = slot.CreatorId != user.UserId && visitedLevel != null && yourReview == null;
if (canNowReviewLevel)
{
RatedLevel? ratedLevel = await this.database.RatedLevels.FirstOrDefaultAsync
(r => r.UserId == user.UserId && r.SlotId == slotId && r.Slot.GameVersion <= gameVersion);
yourReview = new Review();
yourReview.ReviewerId = user.UserId;
yourReview.Reviewer = user;
yourReview.Thumb = ratedLevel?.Rating == null ? 0 : ratedLevel.Rating;
yourReview.Slot = slot;
yourReview.SlotId = slotId;
yourReview.Deleted = false;
yourReview.DeletedBy = DeletedBy.None;
yourReview.Text = "You haven't reviewed this level yet. Edit this blank review to upload one!";
yourReview.LabelCollection = "";
yourReview.Timestamp = TimeHelper.UnixTimeMilliseconds();
}
IQueryable<Review?> reviews = this.database.Reviews.Where(r => r.SlotId == slotId && r.Slot.GameVersion <= gameVersion)
.Include(r => r.Reviewer)
.Include(r => r.Slot)
.AsEnumerable() // performance? Needed for next line (ThumbsUp is not in DB)
.OrderByDescending(r => r.ThumbsUp)
.ThenByDescending(_ => rand.Next())
.ThenByDescending(_ => EF.Functions.Random())
.Skip(pageStart - 1)
.Take(pageSize);
string inner = Enumerable.Aggregate(reviews, string.Empty, (current, review) => {
RatedLevel? ratedLevel = this.database.RatedLevels.FirstOrDefault(r => r.SlotId == slotId && r.UserId == review.ReviewerId);
RatedReview? ratedReview = this.database.RatedReviews.FirstOrDefault(r => r.ReviewId == review.ReviewId && r.UserId == user.UserId);
return current + review.Serialize(ratedLevel, ratedReview);
});
string response = LbpSerializer.TaggedStringElement("reviews", inner, new Dictionary<string, object>
IEnumerable<Review?> prependedReviews;
if (canNowReviewLevel) // this can only be true if you have not posted a review but have visited the level
// prepend the fake review to the top of the list to be easily edited
prependedReviews = reviews.ToList().Prepend(yourReview);
else prependedReviews = reviews.ToList();
string inner = prependedReviews.Aggregate
(
string.Empty,
(current, review) =>
{
if (review == null) return current;
return current + review.Serialize();
}
);
string response = LbpSerializer.TaggedStringElement
(
"reviews",
inner,
new Dictionary<string, object>
{
{
{
"hint_start", pageStart + pageSize
},
{
"hint", pageStart // not sure
},
});
"hint_start", pageStart + pageSize
},
{
"hint", pageStart // not sure
},
}
);
return this.Ok(response);
}
[HttpGet("reviewsBy/{username}")]
public async Task<IActionResult> ReviewsBy(string username, [FromQuery] int pageStart = 1, [FromQuery] int pageSize = 10)
public async Task<IActionResult> ReviewsBy(string username, [FromQuery] int pageStart = 1, [FromQuery] int pageSize = 10)
{
User? user = await this.database.UserFromRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
(User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request);
Token? token = await this.database.TokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
if (userAndToken == null) return this.StatusCode(403, "");
GameVersion gameVersion = token.GameVersion;
// ReSharper disable once PossibleInvalidOperationException
User user = userAndToken.Value.Item1;
GameToken gameToken = userAndToken.Value.Item2;
GameVersion gameVersion = gameToken.GameVersion;
IEnumerable<Review> reviews = this.database.Reviews.Where(r => r.Reviewer.Username == username && r.Slot.GameVersion <= gameVersion)
.Include(r => r.Reviewer)
.Include(r => r.Slot)
.AsEnumerable() // performance?
.OrderByDescending(r => r.Timestamp)
.Skip(pageStart - 1)
.Take(pageSize);
string inner = Enumerable.Aggregate(reviews, string.Empty, (current, review) => {
RatedLevel? ratedLevel = this.database.RatedLevels.FirstOrDefault(r => r.SlotId == review.SlotId && r.UserId == user.UserId);
RatedReview? ratedReview = this.database.RatedReviews.FirstOrDefault(r => r.ReviewId == review.ReviewId && r.UserId == user.UserId);
return current + review.Serialize(ratedLevel, ratedReview);
});
string response = LbpSerializer.TaggedStringElement("reviews", inner, new Dictionary<string, object>
string inner = reviews.Aggregate
(
string.Empty,
(current, review) =>
{
//RatedLevel? ratedLevel = this.database.RatedLevels.FirstOrDefault(r => r.SlotId == review.SlotId && r.UserId == user.UserId);
//RatedReview? ratedReview = this.database.RatedReviews.FirstOrDefault(r => r.ReviewId == review.ReviewId && r.UserId == user.UserId);
return current + review.Serialize( /*, ratedReview*/);
}
);
string response = LbpSerializer.TaggedStringElement
(
"reviews",
inner,
new Dictionary<string, object>
{
{
{
"hint_start", pageStart
},
{
"hint", reviews.Last().Timestamp // Seems to be the timestamp of oldest
},
});
"hint_start", pageStart
},
{
"hint", reviews.Last().Timestamp // Seems to be the timestamp of oldest
},
}
);
return this.Ok(response);
}
[HttpPost("rateReview/user/{slotId:int}/{username}")]
public async Task<IActionResult> RateReview(int slotId, string username, [FromQuery] int rating = 0) {
User? user = await this.database.UserFromRequest(this.Request);
public async Task<IActionResult> RateReview(int slotId, string username, [FromQuery] int rating = 0)
{
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
User? reviewer = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
if (reviewer == null) return this.StatusCode(403, "");
if (reviewer == null) return this.StatusCode(400, "");
Review? review = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == slotId && r.ReviewerId == reviewer.UserId);
if (review == null) return this.StatusCode(403, "");
if (review == null) return this.StatusCode(400, "");
RatedReview? ratedReview = await this.database.RatedReviews.FirstOrDefaultAsync(r => r.ReviewId == review.ReviewId && r.UserId == user.UserId);
if (ratedReview == null)
@ -220,15 +284,26 @@ namespace LBPUnion.ProjectLighthouse.Controllers
this.database.RatedReviews.Add(ratedReview);
}
int oldThumb = ratedReview.Thumb;
ratedReview.Thumb = Math.Max(Math.Min(1, rating), -1);
if (oldThumb != ratedReview.Thumb)
{
if (oldThumb == -1) review.ThumbsDown--;
else if (oldThumb == 1) review.ThumbsUp--;
if (ratedReview.Thumb == -1) review.ThumbsDown++;
else if (ratedReview.Thumb == 1) review.ThumbsUp++;
}
await this.database.SaveChangesAsync();
return this.Ok();
}
[HttpPost("deleteReview/user/{slotId:int}/{username}")]
public async Task<IActionResult> DeleteReview(int slotId, string username) {
public async Task<IActionResult> DeleteReview(int slotId, string username)
{
User? reviewer = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
if (reviewer == null) return this.StatusCode(403, "");
@ -236,7 +311,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
if (review == null) return this.StatusCode(403, "");
review.Deleted = true;
review.DeletedBy = "level_author"; // other value is "moderator"
review.DeletedBy = DeletedBy.LevelAuthor;
await this.database.SaveChangesAsync();
return this.Ok();
@ -252,6 +327,5 @@ namespace LBPUnion.ProjectLighthouse.Controllers
return review;
}
}
}

View file

@ -28,13 +28,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("scoreboard/user/{id:int}")]
public async Task<IActionResult> SubmitScore(int id, [FromQuery] bool lbp1 = false, [FromQuery] bool lbp2 = false, [FromQuery] bool lbp3 = false)
{
(User, Token)? userAndToken = await this.database.UserAndTokenFromRequest(this.Request);
(User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request);
if (userAndToken == null) return this.StatusCode(403, "");
// ReSharper disable once PossibleInvalidOperationException
User user = userAndToken.Value.Item1;
Token token = userAndToken.Value.Item2;
GameToken gameToken = userAndToken.Value.Item2;
this.Request.Body.Position = 0;
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
@ -48,7 +48,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
Slot? slot = this.database.Slots.FirstOrDefault(s => s.SlotId == score.SlotId);
if (slot == null) return this.BadRequest();
switch (token.GameVersion)
switch (gameToken.GameVersion)
{
case GameVersion.LittleBigPlanet1:
slot.PlaysLBP1Complete++;
@ -80,7 +80,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
await this.database.SaveChangesAsync();
string myRanking = GetScores(score.SlotId, score.Type, user);
string myRanking = this.GetScores(score.SlotId, score.Type, user);
return this.Ok(myRanking);
}
@ -95,11 +95,11 @@ namespace LBPUnion.ProjectLighthouse.Controllers
public async Task<IActionResult> TopScores(int slotId, int type, [FromQuery] int pageStart = -1, [FromQuery] int pageSize = 5)
{
// Get username
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
return this.Ok(GetScores(slotId, type, user, pageStart, pageSize));
return this.Ok(this.GetScores(slotId, type, user, pageStart, pageSize));
}
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
@ -139,17 +139,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers
);
string res;
if (myScore == null)
{
res = LbpSerializer.StringElement("scores", serializedScores);
}
if (myScore == null) res = LbpSerializer.StringElement("scores", serializedScores);
else
{
res = LbpSerializer.TaggedStringElement
(
"scores",
serializedScores,
new Dictionary<string, object>()
new Dictionary<string, object>
{
{
"yourScore", myScore.Score.Points
@ -162,7 +158,6 @@ namespace LBPUnion.ProjectLighthouse.Controllers
}, // This is the denominator of your position globally in the side menu.
}
);
}
return res;
}

View file

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types.Levels;
using Microsoft.AspNetCore.Mvc;
@ -44,14 +44,11 @@ namespace LBPUnion.ProjectLighthouse.Controllers
s.SlotId.ToString().Equals(keyword)
);
List<Slot> slots = await dbQuery
.Skip(pageStart - 1)
.Take(Math.Min(pageSize, 30))
.ToListAsync();
List<Slot> slots = await dbQuery.Skip(pageStart - 1).Take(Math.Min(pageSize, 30)).ToListAsync();
string response = slots.Aggregate("", (current, slot) => current + slot.Serialize());
return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "total", dbQuery.Count()));
}
}
}
}

View file

@ -3,11 +3,11 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Levels;
using LBPUnion.ProjectLighthouse.Types.Settings;
using LBPUnion.ProjectLighthouse.Types.Reviews;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@ -27,7 +27,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpGet("slots/by")]
public async Task<IActionResult> SlotsBy([FromQuery] string u, [FromQuery] int pageStart, [FromQuery] int pageSize)
{
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
GameVersion gameVersion = token.GameVersion;
@ -42,7 +42,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
.Include(s => s.Location)
.Where(s => s.Creator!.Username == user.Username)
.Skip(pageStart - 1)
.Take(Math.Min(pageSize, ServerStatics.EntitledSlots)),
.Take(Math.Min(pageSize, ServerSettings.Instance.EntitledSlots)),
string.Empty,
(current, slot) => current + slot.Serialize()
);
@ -56,7 +56,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
new Dictionary<string, object>
{
{
"hint_start", pageStart + Math.Min(pageSize, ServerStatics.EntitledSlots)
"hint_start", pageStart + Math.Min(pageSize, ServerSettings.Instance.EntitledSlots)
},
{
"total", user.UsedSlots
@ -69,10 +69,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpGet("s/user/{id:int}")]
public async Task<IActionResult> SUser(int id)
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
GameVersion gameVersion = token.GameVersion;
@ -86,13 +86,12 @@ namespace LBPUnion.ProjectLighthouse.Controllers
RatedLevel? ratedLevel = await this.database.RatedLevels.FirstOrDefaultAsync(r => r.SlotId == id && r.UserId == user.UserId);
VisitedLevel? visitedLevel = await this.database.VisitedLevels.FirstOrDefaultAsync(r => r.SlotId == id && r.UserId == user.UserId);
Review? yourReview = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == id && r.ReviewerId == user.UserId);
return this.Ok(slot.Serialize(ratedLevel, visitedLevel, yourReview));
return this.Ok(slot.Serialize(ratedLevel, visitedLevel));
}
[HttpGet("slots/lbp2cool")]
[HttpGet("slots/cool")]
public async Task<IActionResult> CoolSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] string gameFilterType, [FromQuery] int players, [FromQuery] Boolean move, [FromQuery] int? page = null)
public async Task<IActionResult> CoolSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] string gameFilterType, [FromQuery] int players, [FromQuery] Boolean move, [FromQuery] int? page = null)
{
int _pageStart = pageStart;
if (page != null) _pageStart = (int)page * 30;
@ -103,7 +102,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpGet("slots")]
public async Task<IActionResult> NewestSlots([FromQuery] int pageStart, [FromQuery] int pageSize)
{
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
GameVersion gameVersion = token.GameVersion;
@ -116,13 +115,29 @@ namespace LBPUnion.ProjectLighthouse.Controllers
.Take(Math.Min(pageSize, 30));
string response = Enumerable.Aggregate(slots, string.Empty, (current, slot) => current + slot.Serialize());
return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "hint_start", pageStart + Math.Min(pageSize, 30)));
return this.Ok
(
LbpSerializer.TaggedStringElement
(
"slots",
response,
new Dictionary<string, object>
{
{
"hint_start", pageStart + Math.Min(pageSize, ServerSettings.Instance.EntitledSlots)
},
{
"total", await StatisticsHelper.SlotCount()
},
}
)
);
}
[HttpGet("slots/mmpicks")]
public async Task<IActionResult> TeamPickedSlots([FromQuery] int pageStart, [FromQuery] int pageSize)
{
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
GameVersion gameVersion = token.GameVersion;
@ -136,13 +151,29 @@ namespace LBPUnion.ProjectLighthouse.Controllers
.Take(Math.Min(pageSize, 30));
string response = Enumerable.Aggregate(slots, string.Empty, (current, slot) => current + slot.Serialize());
return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "hint_start", pageStart + Math.Min(pageSize, 30)));
return this.Ok
(
LbpSerializer.TaggedStringElement
(
"slots",
response,
new Dictionary<string, object>
{
{
"hint_start", pageStart + Math.Min(pageSize, ServerSettings.Instance.EntitledSlots)
},
{
"total", await StatisticsHelper.MMPicksCount()
},
}
)
);
}
[HttpGet("slots/lbp2luckydip")]
public async Task<IActionResult> LuckyDipSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] int seed)
{
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
GameVersion gameVersion = token.GameVersion;
@ -155,15 +186,31 @@ namespace LBPUnion.ProjectLighthouse.Controllers
string response = slots.Aggregate(string.Empty, (current, slot) => current + slot.Serialize());
return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "hint_start", pageStart + Math.Min(pageSize, 30)));
return this.Ok
(
LbpSerializer.TaggedStringElement
(
"slots",
response,
new Dictionary<string, object>
{
{
"hint_start", pageStart + Math.Min(pageSize, ServerSettings.Instance.EntitledSlots)
},
{
"total", await StatisticsHelper.SlotCount()
},
}
)
);
}
[HttpGet("slots/thumbs")]
public async Task<IActionResult> ThumbsSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] string gameFilterType, [FromQuery] int players, [FromQuery] Boolean move, [FromQuery] string? dateFilterType = null)
public async Task<IActionResult> ThumbsSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] string gameFilterType, [FromQuery] int players, [FromQuery] Boolean move, [FromQuery] string? dateFilterType = null)
{
// v--- not sure of API in LBP3 here, needs testing
// v--- not sure of API in LBP3 here, needs testing
GameVersion gameVersion = gameFilterType == "both" ? GameVersion.LittleBigPlanet2 : GameVersion.LittleBigPlanet1;
long oldestTime;
string _dateFilterType = dateFilterType != null ? dateFilterType : "";
@ -198,11 +245,11 @@ namespace LBPUnion.ProjectLighthouse.Controllers
}
[HttpGet("slots/mostUniquePlays")]
public async Task<IActionResult> MostUniquePlaysSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] string gameFilterType, [FromQuery] int players, [FromQuery] Boolean move, [FromQuery] string? dateFilterType = null)
public async Task<IActionResult> MostUniquePlaysSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] string gameFilterType, [FromQuery] int players, [FromQuery] Boolean move, [FromQuery] string? dateFilterType = null)
{
// v--- not sure of API in LBP3 here, needs testing
// v--- not sure of API in LBP3 here, needs testing
GameVersion gameVersion = gameFilterType == "both" ? GameVersion.LittleBigPlanet2 : GameVersion.LittleBigPlanet1;
long oldestTime;
string _dateFilterType = dateFilterType != null ? dateFilterType : "";
@ -226,9 +273,11 @@ namespace LBPUnion.ProjectLighthouse.Controllers
.Include(s => s.Creator)
.Include(s => s.Location)
.AsEnumerable()
.OrderByDescending(s => {
.OrderByDescending(s =>
{
// probably not the best way to do this
switch (gameVersion) {
switch (gameVersion)
{
case GameVersion.LittleBigPlanet1:
return s.PlaysLBP1Unique;
case GameVersion.LittleBigPlanet2:
@ -251,11 +300,11 @@ namespace LBPUnion.ProjectLighthouse.Controllers
}
[HttpGet("slots/mostHearted")]
public async Task<IActionResult> MostHeartedSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] string gameFilterType, [FromQuery] int players, [FromQuery] Boolean move, [FromQuery] string? dateFilterType = null)
public async Task<IActionResult> MostHeartedSlots([FromQuery] int pageStart, [FromQuery] int pageSize, [FromQuery] string gameFilterType, [FromQuery] int players, [FromQuery] Boolean move, [FromQuery] string? dateFilterType = null)
{
// v--- not sure of API in LBP3 here, needs testing
// v--- not sure of API in LBP3 here, needs testing
GameVersion gameVersion = gameFilterType == "both" ? GameVersion.LittleBigPlanet2 : GameVersion.LittleBigPlanet1;
long oldestTime;
string _dateFilterType = dateFilterType != null ? dateFilterType : "";

View file

@ -29,18 +29,17 @@ namespace LBPUnion.ProjectLighthouse.Controllers
public async Task<string?> GetSerializedUser(string username, GameVersion gameVersion = GameVersion.LittleBigPlanet1)
{
User? user = await this.database.Users.Include(u => u.Location).FirstOrDefaultAsync(u => u.Username == username);
if (user == null) return "";
return user.Serialize(gameVersion);
return user?.Serialize(gameVersion);
}
[HttpGet("user/{username}")]
public async Task<IActionResult> GetUser(string username)
{
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
string? user = await this.GetSerializedUser(username, token.GameVersion);
if (user == "") return this.NotFound();
if (user == null) return this.NotFound();
return this.Ok(user);
}
@ -48,15 +47,11 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpGet("users")]
public async Task<IActionResult> GetUserAlt([FromQuery] string[] u)
{
Token? token = await this.database.TokenFromRequest(this.Request);
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
List<string?> serializedUsers = new();
foreach (string username in u)
{
string? serializedUser = await this.GetSerializedUser(username, token.GameVersion);
if (serializedUser != "") serializedUsers.Add(serializedUser);
}
foreach (string userId in u) serializedUsers.Add(await this.GetSerializedUser(userId, token.GameVersion));
string serialized = serializedUsers.Aggregate(string.Empty, (current, user) => user == null ? current : current + user);
@ -69,7 +64,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("updateUser")]
public async Task<IActionResult> UpdateUser()
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
XmlReaderSettings settings = new()
@ -132,6 +127,21 @@ namespace LBPUnion.ProjectLighthouse.Controllers
user.PlanetHash = await reader.GetValueAsync();
break;
}
case "yay2":
{
user.YayHash = await reader.GetValueAsync();
break;
}
case "boo2":
{
user.BooHash = await reader.GetValueAsync();
break;
}
case "meh2":
{
user.MehHash = await reader.GetValueAsync();
break;
}
}
break;
@ -146,10 +156,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
{
Location? l = await this.database.Locations.FirstOrDefaultAsync(l => l.Id == user.LocationId); // find the location in the database again
if (l == null)
{
throw new Exception("this shouldn't happen ever but we handle this");
}
if (l == null) throw new Exception("this shouldn't happen ever but we handle this");
// set the location in the database to the one we modified above
l.X = user.Location.X;
@ -165,7 +172,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
[HttpPost("update_my_pins")]
public async Task<IActionResult> UpdateMyPins()
{
User? user = await this.database.UserFromRequest(this.Request);
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
string pinsString = await new StreamReader(this.Request.Body).ReadToEndAsync();

View file

@ -0,0 +1,73 @@
#nullable enable
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Levels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Controllers.Website.Admin
{
[ApiController]
[Route("admin/slot/{id:int}")]
public class AdminSlotController : ControllerBase
{
private readonly Database database;
public AdminSlotController(Database database)
{
this.database = database;
}
[Route("teamPick")]
public async Task<IActionResult> TeamPick([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null || !user.IsAdmin) return this.StatusCode(403, "");
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.NotFound();
slot.TeamPick = true;
await this.database.SaveChangesAsync();
return this.Ok();
}
[Route("removeTeamPick")]
public async Task<IActionResult> RemoveTeamPick([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null || !user.IsAdmin) return this.StatusCode(403, "");
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.NotFound();
slot.TeamPick = false;
await this.database.SaveChangesAsync();
return this.Ok();
}
[Route("delete")]
public async Task<IActionResult> DeleteLevel([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null || !user.IsAdmin) return this.StatusCode(403, "");
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.Ok();
if (slot.Location == null) throw new ArgumentNullException();
this.database.Locations.Remove(slot.Location);
this.database.Slots.Remove(slot);
await this.database.SaveChangesAsync();
return this.Ok();
}
}
}

View file

@ -0,0 +1,91 @@
#nullable enable
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Controllers.Website.ExternalAuth
{
[ApiController]
[Route("/authentication")]
public class AuthenticationController : ControllerBase
{
private readonly Database database;
public AuthenticationController(Database database)
{
this.database = database;
}
[HttpGet("approve/{id:int}")]
public async Task<IActionResult> Approve(int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("/login");
AuthenticationAttempt? authAttempt = await this.database.AuthenticationAttempts.Include
(a => a.GameToken)
.FirstOrDefaultAsync(a => a.AuthenticationAttemptId == id);
if (authAttempt == null) return this.NotFound();
if (authAttempt.GameToken.UserId != user.UserId) return this.StatusCode(403, "");
authAttempt.GameToken.Approved = true;
this.database.AuthenticationAttempts.Remove(authAttempt);
await this.database.SaveChangesAsync();
return this.Redirect("~/authentication");
}
[HttpGet("deny/{id:int}")]
public async Task<IActionResult> Deny(int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("/login");
AuthenticationAttempt? authAttempt = await this.database.AuthenticationAttempts.Include
(a => a.GameToken)
.FirstOrDefaultAsync(a => a.AuthenticationAttemptId == id);
if (authAttempt == null) return this.NotFound();
if (authAttempt.GameToken.UserId != user.UserId) return this.StatusCode(403, "");
this.database.GameTokens.Remove(authAttempt.GameToken);
this.database.AuthenticationAttempts.Remove(authAttempt);
DeniedAuthenticationHelper.SetDeniedAt($"{authAttempt.IPAddress}|{user.Username}");
await this.database.SaveChangesAsync();
return this.Redirect("~/authentication");
}
[HttpGet("denyAll")]
public async Task<IActionResult> DenyAll()
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("/login");
List<AuthenticationAttempt> authAttempts = await this.database.AuthenticationAttempts.Include
(a => a.GameToken)
.Where(a => a.GameToken.UserId == user.UserId)
.ToListAsync();
foreach (AuthenticationAttempt authAttempt in authAttempts)
{
this.database.GameTokens.Remove(authAttempt.GameToken);
this.database.AuthenticationAttempts.Remove(authAttempt);
DeniedAuthenticationHelper.SetDeniedAt($"{authAttempt.IPAddress}|{user.Username}");
}
await this.database.SaveChangesAsync();
return this.Redirect("~/authentication");
}
}
}

View file

@ -0,0 +1,90 @@
#nullable enable
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Levels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
// I would like to apologize in advance for anyone dealing with this file.
// Theres probably a better way to do this with delegates but I'm tired.
// TODO: Clean up this file
// - jvyden
namespace LBPUnion.ProjectLighthouse.Controllers.Website
{
[ApiController]
[Route("slot/{id:int}")]
public class SlotPageController : ControllerBase
{
private readonly Database database;
public SlotPageController(Database database)
{
this.database = database;
}
[HttpGet("heart")]
public async Task<IActionResult> HeartLevel([FromRoute] int id, [FromQuery] string? callbackUrl)
{
if (string.IsNullOrEmpty(callbackUrl)) callbackUrl = "~/slot/" + id;
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
Slot? heartedSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (heartedSlot == null) return this.NotFound();
await this.database.HeartLevel(user, heartedSlot);
return this.Redirect(callbackUrl);
}
[HttpGet("unheart")]
public async Task<IActionResult> UnheartLevel([FromRoute] int id, [FromQuery] string? callbackUrl)
{
if (string.IsNullOrEmpty(callbackUrl)) callbackUrl = "~/slot/" + id;
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
Slot? heartedSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (heartedSlot == null) return this.NotFound();
await this.database.UnheartLevel(user, heartedSlot);
return this.Redirect(callbackUrl);
}
[HttpGet("queue")]
public async Task<IActionResult> QueueLevel([FromRoute] int id, [FromQuery] string? callbackUrl)
{
if (string.IsNullOrEmpty(callbackUrl)) callbackUrl = "~/slot/" + id;
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
Slot? queuedSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (queuedSlot == null) return this.NotFound();
await this.database.QueueLevel(user, queuedSlot);
return this.Redirect(callbackUrl);
}
[HttpGet("unqueue")]
public async Task<IActionResult> UnqueueLevel([FromRoute] int id, [FromQuery] string? callbackUrl)
{
if (string.IsNullOrEmpty(callbackUrl)) callbackUrl = "~/slot/" + id;
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
Slot? queuedSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (queuedSlot == null) return this.NotFound();
await this.database.UnqueueLevel(user, queuedSlot);
return this.Redirect(callbackUrl);
}
}
}

View file

@ -0,0 +1,48 @@
#nullable enable
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Controllers.Website
{
[ApiController]
[Route("user/{id:int}")]
public class UserPageController : ControllerBase
{
private readonly Database database;
public UserPageController(Database database)
{
this.database = database;
}
[HttpGet("heart")]
public async Task<IActionResult> HeartUser([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
User? heartedUser = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id);
if (heartedUser == null) return this.NotFound();
await this.database.HeartUser(user, heartedUser);
return this.Redirect("~/user/" + id);
}
[HttpGet("unheart")]
public async Task<IActionResult> UnheartUser([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
User? heartedUser = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id);
if (heartedUser == null) return this.NotFound();
await this.database.UnheartUser(user, heartedUser);
return this.Redirect("~/user/" + id);
}
}
}

View file

@ -1,3 +1,4 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Kettu;
@ -6,8 +7,8 @@ using LBPUnion.ProjectLighthouse.Logging;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Levels;
using LBPUnion.ProjectLighthouse.Types.Profiles;
using LBPUnion.ProjectLighthouse.Types.Settings;
using LBPUnion.ProjectLighthouse.Types.Reviews;
using LBPUnion.ProjectLighthouse.Types.Settings;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
@ -22,21 +23,25 @@ namespace LBPUnion.ProjectLighthouse
public DbSet<HeartedLevel> HeartedLevels { get; set; }
public DbSet<HeartedProfile> HeartedProfiles { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<Token> Tokens { get; set; }
public DbSet<GameToken> GameTokens { get; set; }
public DbSet<WebToken> WebTokens { get; set; }
public DbSet<Score> Scores { get; set; }
public DbSet<PhotoSubject> PhotoSubjects { get; set; }
public DbSet<Photo> Photos { get; set; }
public DbSet<LastMatch> LastMatches { get; set; }
public DbSet<LastContact> LastContacts { get; set; }
public DbSet<VisitedLevel> VisitedLevels { get; set; }
public DbSet<RatedLevel> RatedLevels { get; set; }
public DbSet<AuthenticationAttempt> AuthenticationAttempts { get; set; }
public DbSet<Review> Reviews { get; set; }
public DbSet<RatedReview> RatedReviews { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseMySql(ServerSettings.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
public async Task<User> CreateUser(string username)
public async Task<User> CreateUser(string username, string password)
{
if (!password.StartsWith("$")) throw new ArgumentException(nameof(password) + " is not a BCrypt hash");
User user;
if ((user = await this.Users.Where(u => u.Username == username).FirstOrDefaultAsync()) != null) return user;
@ -47,6 +52,7 @@ namespace LBPUnion.ProjectLighthouse
user = new User
{
Username = username,
Password = password,
LocationId = l.Id,
Biography = username + " hasn't introduced themselves yet.",
};
@ -58,12 +64,13 @@ namespace LBPUnion.ProjectLighthouse
}
#nullable enable
public async Task<Token?> AuthenticateUser(LoginData loginData, string userLocation, string titleId = "")
public async Task<GameToken?> AuthenticateUser(LoginData loginData, string userLocation, string titleId = "")
{
// TODO: don't use psn name to authenticate
User user = await this.Users.FirstOrDefaultAsync(u => u.Username == loginData.Username) ?? await this.CreateUser(loginData.Username);
User? user = await this.Users.FirstOrDefaultAsync(u => u.Username == loginData.Username);
if (user == null) return null;
Token token = new()
GameToken gameToken = new()
{
UserToken = HashHelper.GenerateAuthToken(),
UserId = user.UserId,
@ -71,58 +78,214 @@ namespace LBPUnion.ProjectLighthouse
GameVersion = GameVersionHelper.FromTitleId(titleId),
};
if (token.GameVersion == GameVersion.Unknown)
if (gameToken.GameVersion == GameVersion.Unknown)
{
Logger.Log($"Unknown GameVersion for TitleId {titleId}", LoggerLevelLogin.Instance);
return null;
}
this.Tokens.Add(token);
this.GameTokens.Add(gameToken);
await this.SaveChangesAsync();
return token;
return gameToken;
}
public async Task<User?> UserFromAuthToken(string authToken)
#region Hearts & Queues
public async Task HeartUser(User user, User heartedUser)
{
Token? token = await this.Tokens.FirstOrDefaultAsync(t => t.UserToken == authToken);
HeartedProfile? heartedProfile = await this.HeartedProfiles.FirstOrDefaultAsync
(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
if (heartedProfile != null) return;
this.HeartedProfiles.Add
(
new HeartedProfile
{
HeartedUserId = heartedUser.UserId,
UserId = user.UserId,
}
);
await this.SaveChangesAsync();
}
public async Task UnheartUser(User user, User heartedUser)
{
HeartedProfile? heartedProfile = await this.HeartedProfiles.FirstOrDefaultAsync
(q => q.UserId == user.UserId && q.HeartedUserId == heartedUser.UserId);
if (heartedProfile != null) this.HeartedProfiles.Remove(heartedProfile);
await this.SaveChangesAsync();
}
public async Task HeartLevel(User user, Slot heartedSlot)
{
HeartedLevel? heartedLevel = await this.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == heartedSlot.SlotId);
if (heartedLevel != null) return;
this.HeartedLevels.Add
(
new HeartedLevel
{
SlotId = heartedSlot.SlotId,
UserId = user.UserId,
}
);
await this.SaveChangesAsync();
}
public async Task UnheartLevel(User user, Slot heartedSlot)
{
HeartedLevel? heartedLevel = await this.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == heartedSlot.SlotId);
if (heartedLevel != null) this.HeartedLevels.Remove(heartedLevel);
await this.SaveChangesAsync();
}
public async Task QueueLevel(User user, Slot queuedSlot)
{
QueuedLevel? queuedLevel = await this.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == queuedSlot.SlotId);
if (queuedLevel != null) return;
this.QueuedLevels.Add
(
new QueuedLevel
{
SlotId = queuedSlot.SlotId,
UserId = user.UserId,
}
);
await this.SaveChangesAsync();
}
public async Task UnqueueLevel(User user, Slot queuedSlot)
{
QueuedLevel? queuedLevel = await this.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == queuedSlot.SlotId);
if (queuedLevel != null) this.QueuedLevels.Remove(queuedLevel);
await this.SaveChangesAsync();
}
#endregion
#region Game Token Shenanigans
public async Task<User?> UserFromMMAuth(string authToken, bool allowUnapproved = false)
{
if (ServerStatics.IsUnitTesting) allowUnapproved = true;
GameToken? token = await this.GameTokens.FirstOrDefaultAsync(t => t.UserToken == authToken);
if (token == null) return null;
if (!allowUnapproved && !token.Approved) return null;
return await this.Users.Include(u => u.Location).FirstOrDefaultAsync(u => u.UserId == token.UserId);
}
public async Task<User?> UserFromToken(Token token) => await this.UserFromAuthToken(token.UserToken);
public async Task<User?> UserFromGameToken
(GameToken gameToken, bool allowUnapproved = false)
=> await this.UserFromMMAuth(gameToken.UserToken, allowUnapproved);
public async Task<User?> UserFromRequest(HttpRequest request)
public async Task<User?> UserFromGameRequest(HttpRequest request, bool allowUnapproved = false)
{
if (ServerStatics.IsUnitTesting) allowUnapproved = true;
if (!request.Cookies.TryGetValue("MM_AUTH", out string? mmAuth) || mmAuth == null) return null;
return await this.UserFromAuthToken(mmAuth);
return await this.UserFromMMAuth(mmAuth, allowUnapproved);
}
public async Task<Token?> TokenFromRequest(HttpRequest request)
public async Task<GameToken?> GameTokenFromRequest(HttpRequest request, bool allowUnapproved = false)
{
if (ServerStatics.IsUnitTesting) allowUnapproved = true;
if (!request.Cookies.TryGetValue("MM_AUTH", out string? mmAuth) || mmAuth == null) return null;
return await this.Tokens.FirstOrDefaultAsync(t => t.UserToken == mmAuth);
}
GameToken? token = await this.GameTokens.FirstOrDefaultAsync(t => t.UserToken == mmAuth);
public async Task<(User, Token)?> UserAndTokenFromRequest(HttpRequest request)
{
if (!request.Cookies.TryGetValue("MM_AUTH", out string? mmAuth) || mmAuth == null) return null;
Token? token = await this.Tokens.FirstOrDefaultAsync(t => t.UserToken == mmAuth);
if (token == null) return null;
if (!allowUnapproved && !token.Approved) return null;
User? user = await this.UserFromToken(token);
return token;
}
public async Task<(User, GameToken)?> UserAndGameTokenFromRequest(HttpRequest request, bool allowUnapproved = false)
{
if (ServerStatics.IsUnitTesting) allowUnapproved = true;
if (!request.Cookies.TryGetValue("MM_AUTH", out string? mmAuth) || mmAuth == null) return null;
GameToken? token = await this.GameTokens.FirstOrDefaultAsync(t => t.UserToken == mmAuth);
if (token == null) return null;
if (!allowUnapproved && !token.Approved) return null;
User? user = await this.UserFromGameToken(token);
if (user == null) return null;
return (user, token);
}
#endregion
#region Web Token Shenanigans
public User? UserFromLighthouseToken(string lighthouseToken)
{
WebToken? token = this.WebTokens.FirstOrDefault(t => t.UserToken == lighthouseToken);
if (token == null) return null;
return this.Users.Include(u => u.Location).FirstOrDefault(u => u.UserId == token.UserId);
}
public User? UserFromWebRequest(HttpRequest request)
{
if (!request.Cookies.TryGetValue("LighthouseToken", out string? lighthouseToken) || lighthouseToken == null) return null;
return this.UserFromLighthouseToken(lighthouseToken);
}
public WebToken? WebTokenFromRequest(HttpRequest request)
{
if (!request.Cookies.TryGetValue("LighthouseToken", out string? lighthouseToken) || lighthouseToken == null) return null;
return this.WebTokens.FirstOrDefault(t => t.UserToken == lighthouseToken);
}
#endregion
public async Task<Photo?> PhotoFromSubject(PhotoSubject subject)
=> await this.Photos.FirstOrDefaultAsync(p => p.PhotoSubjectIds.Contains(subject.PhotoSubjectId.ToString()));
public async Task RemoveUser(User user)
{
this.Locations.Remove(user.Location);
LastContact? lastContact = await this.LastContacts.FirstOrDefaultAsync(l => l.UserId == user.UserId);
if (lastContact != null) this.LastContacts.Remove(lastContact);
foreach (Slot slot in this.Slots.Where(s => s.CreatorId == user.UserId)) await this.RemoveSlot(slot, false);
this.AuthenticationAttempts.RemoveRange(this.AuthenticationAttempts.Include(a => a.GameToken).Where(a => a.GameToken.UserId == user.UserId));
this.HeartedProfiles.RemoveRange(this.HeartedProfiles.Where(h => h.UserId == user.UserId));
this.PhotoSubjects.RemoveRange(this.PhotoSubjects.Where(s => s.UserId == user.UserId));
this.HeartedLevels.RemoveRange(this.HeartedLevels.Where(h => h.UserId == user.UserId));
this.VisitedLevels.RemoveRange(this.VisitedLevels.Where(v => v.UserId == user.UserId));
this.QueuedLevels.RemoveRange(this.QueuedLevels.Where(q => q.UserId == user.UserId));
this.RatedLevels.RemoveRange(this.RatedLevels.Where(r => r.UserId == user.UserId));
this.GameTokens.RemoveRange(this.GameTokens.Where(t => t.UserId == user.UserId));
this.WebTokens.RemoveRange(this.WebTokens.Where(t => t.UserId == user.UserId));
this.Comments.RemoveRange(this.Comments.Where(c => c.PosterUserId == user.UserId));
this.Photos.RemoveRange(this.Photos.Where(p => p.CreatorId == user.UserId));
await this.SaveChangesAsync();
}
public async Task RemoveSlot(Slot slot, bool saveChanges = true)
{
if (slot.Location != null) this.Locations.Remove(slot.Location);
this.Slots.Remove(slot);
if (saveChanges) await this.SaveChangesAsync();
}
#nullable disable
}
}

View file

@ -6,8 +6,8 @@ namespace LBPUnion.ProjectLighthouse
{
public class FakeRemoteIPAddressMiddleware
{
private readonly RequestDelegate next;
private readonly IPAddress fakeIpAddress = IPAddress.Parse("127.0.0.1");
private readonly RequestDelegate next;
public FakeRemoteIPAddressMiddleware(RequestDelegate next)
{

View file

@ -0,0 +1,38 @@
using System.Collections.Generic;
namespace LBPUnion.ProjectLighthouse.Helpers
{
public static class DeniedAuthenticationHelper
{
public static readonly Dictionary<string, long> IPAddressAndNameDeniedAt = new();
public static readonly Dictionary<string, int> AttemptsByIPAddressAndName = new();
public static void SetDeniedAt(string ipAddressAndName, long timestamp = 0)
{
if (timestamp == 0) timestamp = TimestampHelper.Timestamp;
if (IPAddressAndNameDeniedAt.TryGetValue(ipAddressAndName, out long _)) IPAddressAndNameDeniedAt.Remove(ipAddressAndName);
IPAddressAndNameDeniedAt.Add(ipAddressAndName, timestamp);
}
public static bool RecentlyDenied(string ipAddressAndName)
{
if (!IPAddressAndNameDeniedAt.TryGetValue(ipAddressAndName, out long timestamp)) return false;
return TimestampHelper.Timestamp < timestamp + 300;
}
public static void AddAttempt(string ipAddressAndName)
{
if (AttemptsByIPAddressAndName.TryGetValue(ipAddressAndName, out int attempts)) AttemptsByIPAddressAndName.Remove(ipAddressAndName);
AttemptsByIPAddressAndName.Add(ipAddressAndName, attempts + 1);
}
public static int GetAttempts(string ipAddressAndName)
{
if (!AttemptsByIPAddressAndName.TryGetValue(ipAddressAndName, out int attempts)) return 0;
return attempts;
}
}
}

View file

@ -3,6 +3,7 @@ using System.IO;
using System.Linq;
using System.Text;
using LBPUnion.ProjectLighthouse.Types.Files;
using LBPUnion.ProjectLighthouse.Types.Settings;
namespace LBPUnion.ProjectLighthouse.Helpers
{
@ -14,6 +15,8 @@ namespace LBPUnion.ProjectLighthouse.Helpers
public static bool IsFileSafe(LbpFile file)
{
if (!ServerSettings.Instance.CheckForUnsafeFiles) return true;
if (file.FileType == LbpFileType.Unknown) file.FileType = DetermineFileType(file.Data);
return file.FileType switch

View file

@ -44,6 +44,7 @@ namespace LBPUnion.ProjectLighthouse.Helpers
"BCES01346",
"BCUS90260",
"BCET70023",
"BCES01694",
"NPUA80662",
};

View file

@ -67,7 +67,7 @@ namespace LBPUnion.ProjectLighthouse.Helpers
public static string Sha256Hash(string str) => Sha256Hash(Encoding.UTF8.GetBytes(str));
public static string Sha256Hash(byte[] bytes) => BitConverter.ToString(sha256.ComputeHash(bytes)).Replace("-", "");
public static string Sha256Hash(byte[] bytes) => BitConverter.ToString(sha256.ComputeHash(bytes)).Replace("-", "").ToLower();
public static string Sha1Hash(string str) => Sha1Hash(Encoding.UTF8.GetBytes(str));

View file

@ -0,0 +1,35 @@
#nullable enable
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Profiles;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Helpers
{
public static class LastContactHelper
{
private static readonly Database database = new();
public static async Task SetLastContact(User user, GameVersion gameVersion)
{
LastContact? lastContact = await database.LastContacts.Where(l => l.UserId == user.UserId).FirstOrDefaultAsync();
// below makes it not look like trash
// ReSharper disable once ConvertIfStatementToNullCoalescingExpression
if (lastContact == null)
{
lastContact = new LastContact
{
UserId = user.UserId,
};
database.LastContacts.Add(lastContact);
}
lastContact.Timestamp = TimestampHelper.Timestamp;
lastContact.GameVersion = gameVersion;
await database.SaveChangesAsync();
}
}
}

View file

@ -0,0 +1,70 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Maintenance;
namespace LBPUnion.ProjectLighthouse.Helpers
{
public static class MaintenanceHelper
{
static MaintenanceHelper()
{
Commands = getListOfInterfaceObjects<ICommand>();
MaintenanceJobs = getListOfInterfaceObjects<IMaintenanceJob>();
}
public static List<ICommand> Commands { get; }
public static List<IMaintenanceJob> MaintenanceJobs { get; }
private static List<T> getListOfInterfaceObjects<T>() where T : class
{
return Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.GetInterfaces().Contains(typeof(T)) && t.GetConstructor(Type.EmptyTypes) != null)
.Select(t => Activator.CreateInstance(t) as T)
.ToList()!;
}
public static async Task RunCommand(string[] args)
{
if (args.Length < 1)
throw new Exception
(
"This should never happen. " +
"If it did, its because you tried to run a command before validating that the user actually wants to run one."
);
string baseCmd = args[0];
args = args.Skip(1).ToArray();
IEnumerable<ICommand> suitableCommands = Commands.Where
(command => command.Aliases().Any(a => a.ToLower() == baseCmd.ToLower()))
.Where(command => args.Length >= command.RequiredArgs());
foreach (ICommand command in suitableCommands)
{
Console.WriteLine("Running command " + command.Name());
await command.Run(args);
return;
}
Console.WriteLine("Command not found.");
}
public static async Task RunMaintenanceJob(string jobName)
{
IMaintenanceJob? job = MaintenanceJobs.FirstOrDefault(j => j.GetType().Name == jobName);
if (job == null) throw new ArgumentNullException();
await RunMaintenanceJob(job);
}
public static async Task RunMaintenanceJob(IMaintenanceJob job)
{
await job.Run();
}
}
}

View file

@ -22,10 +22,7 @@ namespace LBPUnion.ProjectLighthouse.Helpers
public static void AddUserRecentlyDivedIn(int userId, int otherUserId)
{
if (!UserRecentlyDivedIn.TryGetValue(userId, out List<int>? recentlyDivedIn))
{
UserRecentlyDivedIn.Add(userId, recentlyDivedIn = new List<int>());
}
if (!UserRecentlyDivedIn.TryGetValue(userId, out List<int>? recentlyDivedIn)) UserRecentlyDivedIn.Add(userId, recentlyDivedIn = new List<int>());
Debug.Assert(recentlyDivedIn != null, nameof(recentlyDivedIn) + " is null, somehow.");

View file

@ -43,10 +43,7 @@ namespace LBPUnion.ProjectLighthouse.Helpers
{
bool gotValue = MatchHelper.UserLocations.TryGetValue(p.UserId, out string? value);
if (gotValue && value != null)
{
relevantUserLocations.Add(p.UserId, value);
}
if (gotValue && value != null) relevantUserLocations.Add(p.UserId, value);
return gotValue;
}
);
@ -138,20 +135,23 @@ namespace LBPUnion.ProjectLighthouse.Helpers
{
// Delete old rooms based on host
if (host != null)
{
Rooms.RemoveAll(r => r.Host == host);
}
try
{
Rooms.RemoveAll(r => r.Host == host);
}
catch
{
// TODO: detect the room that failed and remove it
}
// Remove players in this new room from other rooms
if (newRoom != null)
{
foreach (Room room in Rooms)
{
if (room == newRoom) continue;
foreach (User newRoomPlayer in newRoom.Players) room.Players.RemoveAll(p => p == newRoomPlayer);
}
}
}
}
}

View file

@ -8,10 +8,12 @@ namespace LBPUnion.ProjectLighthouse.Helpers
{
private static readonly Database database = new();
public static async Task<int> RecentMatches() => await database.LastMatches.Where(l => TimestampHelper.Timestamp - l.Timestamp < 300).CountAsync();
public static async Task<int> RecentMatches() => await database.LastContacts.Where(l => TimestampHelper.Timestamp - l.Timestamp < 300).CountAsync();
public static async Task<int> SlotCount() => await database.Slots.CountAsync();
public static async Task<int> MMPicksCount() => await database.Slots.CountAsync(s => s.TeamPick);
public static async Task<int> PhotoCount() => await database.Photos.CountAsync();
}
}

View file

@ -2,12 +2,13 @@ using System;
using System.IO;
using Kettu;
using LBPUnion.ProjectLighthouse.Logging;
using LBPUnion.ProjectLighthouse.Types.Settings;
namespace LBPUnion.ProjectLighthouse.Helpers
{
public static class GitVersionHelper
public static class VersionHelper
{
static GitVersionHelper()
static VersionHelper()
{
try
{
@ -50,7 +51,17 @@ namespace LBPUnion.ProjectLighthouse.Helpers
public static string CommitHash { get; set; }
public static string Branch { get; set; }
public static string FullVersion => $"{ServerStatics.ServerName} {Branch}@{CommitHash} {Build}";
public static bool IsDirty => CommitHash.EndsWith("-dirty");
public static bool CanCheckForUpdates { get; set; }
public const string Build =
#if DEBUG
"Debug";
#elif RELEASE
"Release";
#else
"Unknown";
#endif
}
}

View file

@ -8,6 +8,7 @@ namespace LBPUnion.ProjectLighthouse.Logging
{
public class InfluxLogger : LoggerBase
{
public override bool AllowMultiple => false;
public override void Send(LoggerLine line)
{
@ -22,6 +23,5 @@ namespace LBPUnion.ProjectLighthouse.Logging
writeApi.WritePoint(ServerSettings.Instance.InfluxBucket, ServerSettings.Instance.InfluxOrg, point);
}
public override bool AllowMultiple => false;
}
}

View file

@ -25,7 +25,7 @@ namespace LBPUnion.ProjectLighthouse.Logging
File.AppendAllText(Path.Combine(logsDirectory, line.LoggerLevel.Name.ToFileName() + ".log"), contentFile);
File.AppendAllText(Path.Combine(logsDirectory, "all.log"), contentAll);
}
catch (IOException) { } // windows, ya goofed
catch(IOException) {} // windows, ya goofed
}
}

View file

@ -0,0 +1,54 @@
#nullable enable
using System.Threading.Tasks;
using JetBrains.Annotations;
using Kettu;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Logging;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Maintenance.Commands
{
[UsedImplicitly]
public class CreateUserCommand : ICommand
{
private readonly Database _database = new();
public async Task Run(string[] args)
{
string onlineId = args[0];
string password = args[1];
password = HashHelper.Sha256Hash(password);
User? user = await this._database.Users.FirstOrDefaultAsync(u => u.Username == onlineId);
if (user == null)
{
user = await this._database.CreateUser(onlineId, HashHelper.BCryptHash(password));
Logger.Log($"Created user {user.UserId} with online ID (username) {user.Username} and the specified password.", LoggerLevelLogin.Instance);
user.PasswordResetRequired = true;
Logger.Log("This user will need to reset their password when they log in.", LoggerLevelLogin.Instance);
await this._database.SaveChangesAsync();
Logger.Log("Database changes saved.", LoggerLevelDatabase.Instance);
}
else
{
Logger.Log("A user with this username already exists.", LoggerLevelLogin.Instance);
}
}
public string Name() => "Create New User";
public string[] Aliases()
=> new[]
{
"useradd", "adduser", "newuser", "createUser",
};
public string Arguments() => "<OnlineID> <Password>";
public int RequiredArgs() => 2;
}
}

View file

@ -0,0 +1,40 @@
#nullable enable
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Maintenance.Commands
{
[UsedImplicitly]
public class DeleteUserCommand : ICommand
{
private readonly Database database = new();
public string Name() => "Delete/Ban User";
public string[] Aliases()
=> new[]
{
"deleteUser", "wipeUser", "banUser",
};
public string Arguments() => "<username/userId>";
public int RequiredArgs() => 1;
public async Task Run(string[] args)
{
User? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == args[0]);
if (user == null)
try
{
user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == Convert.ToInt32(args[0]));
if (user == null) throw new Exception();
}
catch
{
Console.WriteLine($"Could not find user by parameter '{args[0]}'");
return;
}
await this.database.RemoveUser(user);
}
}
}

View file

@ -0,0 +1,45 @@
#nullable enable
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Maintenance.Commands
{
[UsedImplicitly]
public class MakeUserAdminCommand : ICommand
{
private readonly Database database = new();
public string Name() => "Make User Admin";
public string[] Aliases()
=> new[]
{
"makeAdmin",
};
public string Arguments() => "<username/userId>";
public int RequiredArgs() => 1;
public async Task Run(string[] args)
{
User? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == args[0]);
if (user == null)
try
{
user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == Convert.ToInt32(args[0]));
if (user == null) throw new Exception();
}
catch
{
Console.WriteLine($"Could not find user by parameter '{args[0]}'");
return;
}
user.IsAdmin = true;
await this.database.SaveChangesAsync();
Console.WriteLine($"The user {user.Username} (id: {user.UserId}) is now an admin.");
}
}
}

View file

@ -0,0 +1,49 @@
#nullable enable
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Maintenance.Commands
{
[UsedImplicitly]
public class ResetPasswordCommand : ICommand
{
private readonly Database database = new();
public string Name() => "Reset Password";
public string[] Aliases()
=> new[]
{
"setPassword", "resetPassword", "passwd", "password",
};
public string Arguments() => "<username/userId> <sha256/plaintext>";
public int RequiredArgs() => 2;
public async Task Run(string[] args)
{
User? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == args[0]);
if (user == null)
try
{
user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == Convert.ToInt32(args[0]));
if (user == null) throw new Exception();
}
catch
{
Console.WriteLine($"Could not find user by parameter '{args[0]}'");
return;
}
string password = args[1];
if (password.Length != 64) password = HashHelper.Sha256Hash(password);
user.Password = HashHelper.BCryptHash(password);
user.PasswordResetRequired = true;
await this.database.SaveChangesAsync();
Console.WriteLine($"The password for user {user.Username} (id: {user.UserId}) has been reset.");
}
}
}

View file

@ -0,0 +1,45 @@
#nullable enable
using System;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Maintenance.Commands
{
public class WipeTokensForUserCommand : ICommand
{
private readonly Database database = new();
public string Name() => "Wipe tokens for user";
public string[] Aliases()
=> new[]
{
"wipeTokens", "wipeToken", "deleteTokens", "deleteToken", "removeTokens", "removeToken",
};
public string Arguments() => "<username/userId>";
public int RequiredArgs() => 1;
public async Task Run(string[] args)
{
User? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == args[0]);
if (user == null)
try
{
user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == Convert.ToInt32(args[0]));
if (user == null) throw new Exception();
}
catch
{
Console.WriteLine($"Could not find user by parameter '{args[0]}'");
return;
}
this.database.GameTokens.RemoveRange(this.database.GameTokens.Where(t => t.UserId == user.UserId));
this.database.WebTokens.RemoveRange(this.database.WebTokens.Where(t => t.UserId == user.UserId));
await this.database.SaveChangesAsync();
Console.WriteLine($"Deleted all tokens for {user.Username} (id: {user.UserId}).");
}
}
}

View file

@ -0,0 +1,19 @@
using System.Threading.Tasks;
namespace LBPUnion.ProjectLighthouse.Maintenance
{
public interface ICommand
{
public string FirstAlias => this.Aliases()[0];
public Task Run(string[] args);
public string Name();
public string[] Aliases();
public string Arguments();
public int RequiredArgs();
}
}

View file

@ -0,0 +1,13 @@
using System.Threading.Tasks;
namespace LBPUnion.ProjectLighthouse.Maintenance
{
public interface IMaintenanceJob
{
public Task Run();
public string Name();
public string Description();
}
}

View file

@ -0,0 +1,71 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Files;
namespace LBPUnion.ProjectLighthouse.Maintenance.MaintenanceJobs
{
public class CleanupBrokenPhotosMaintenanceJob : IMaintenanceJob
{
private readonly Database database = new();
public string Name() => "Cleanup Broken Photos";
public string Description() => "Deletes all photos that have missing assets.";
[SuppressMessage("ReSharper", "LoopCanBePartlyConvertedToQuery")]
public async Task Run()
{
foreach (Photo photo in this.database.Photos)
{
bool hashNullOrEmpty = false;
bool noHashesExist = false;
bool largeHashIsInvalidFile = false;
hashNullOrEmpty = string.IsNullOrEmpty
(photo.LargeHash) ||
string.IsNullOrEmpty(photo.MediumHash) ||
string.IsNullOrEmpty(photo.SmallHash) ||
string.IsNullOrEmpty(photo.PlanHash);
if (hashNullOrEmpty) goto removePhoto;
List<string> hashes = new()
{
photo.LargeHash,
photo.MediumHash,
photo.SmallHash,
photo.PlanHash,
};
noHashesExist = FileHelper.ResourcesNotUploaded(hashes.ToArray()).Length != 0;
if (noHashesExist) goto removePhoto;
LbpFile? file = LbpFile.FromHash(photo.LargeHash);
// Console.WriteLine(file.FileType, );
if (file == null || file.FileType != LbpFileType.Jpeg && file.FileType != LbpFileType.Png)
{
largeHashIsInvalidFile = true;
goto removePhoto;
}
continue;
removePhoto:
Console.WriteLine
(
$"Removing photo (id: {photo.PhotoId}): " +
$"{nameof(hashNullOrEmpty)}: {hashNullOrEmpty}, " +
$"{nameof(noHashesExist)}: {noHashesExist}, " +
$"{nameof(largeHashIsInvalidFile)}: {largeHashIsInvalidFile}"
);
this.database.Photos.Remove(photo);
}
await this.database.SaveChangesAsync();
}
}
}

View file

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Types.Profiles;
namespace LBPUnion.ProjectLighthouse.Maintenance.MaintenanceJobs
{
public class CleanupUnusedLocationsMaintenanceJob : IMaintenanceJob
{
private readonly Database database = new();
public string Name() => "Cleanup Unused Locations";
public string Description() => "Cleanup unused locations in the database.";
public async Task Run()
{
List<int> usedLocationIds = new();
usedLocationIds.AddRange(this.database.Slots.Select(slot => slot.LocationId));
usedLocationIds.AddRange(this.database.Users.Select(user => user.LocationId));
IQueryable<Location> locationsToRemove = this.database.Locations.Where(l => !usedLocationIds.Contains(l.Id));
foreach (Location location in locationsToRemove)
{
Console.WriteLine("Removing location " + location.Id);
this.database.Locations.Remove(location);
}
await this.database.SaveChangesAsync();
}
}
}

View file

@ -0,0 +1,22 @@
using System;
using System.Threading.Tasks;
namespace LBPUnion.ProjectLighthouse.Maintenance.MaintenanceJobs
{
public class DeleteAllTokensMaintenanceJob : IMaintenanceJob
{
private readonly Database database = new();
public string Name() => "Delete ALL Tokens";
public string Description() => "Deletes ALL game tokens and web tokens.";
public async Task Run()
{
this.database.GameTokens.RemoveRange(this.database.GameTokens);
this.database.WebTokens.RemoveRange(this.database.WebTokens);
await this.database.SaveChangesAsync();
Console.WriteLine("Deleted ALL tokens.");
}
}
}

View file

@ -0,0 +1,31 @@
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Types.Levels;
namespace LBPUnion.ProjectLighthouse.Maintenance.MaintenanceJobs
{
public class FixAllBrokenPlayerRequirementsMaintenanceJob : IMaintenanceJob
{
private readonly Database database = new();
public string Name() => "Fix All Broken Player Requirements";
public string Description() => "Some LBP1 levels may report that they are designed for 0 players. This job will fix that.";
public async Task Run()
{
int count = 0;
await foreach (Slot slot in this.database.Slots)
if (slot.MinimumPlayers == 0 || slot.MaximumPlayers == 0)
{
slot.MinimumPlayers = 1;
slot.MaximumPlayers = 4;
Console.WriteLine($"Fixed slotId {slot.SlotId}");
count++;
}
await this.database.SaveChangesAsync();
Console.WriteLine($"Fixed {count} broken player requirements.");
}
}
}

View file

@ -154,7 +154,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Slots");
});
modelBuilder.Entity("ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -175,7 +175,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Slots");
});
modelBuilder.Entity("ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -189,7 +189,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Slots");
});
modelBuilder.Entity("ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -189,7 +189,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Slots");
});
modelBuilder.Entity("ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -208,7 +208,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -211,7 +211,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -214,7 +214,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -214,7 +214,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -217,7 +217,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -242,7 +242,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -242,7 +242,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -242,7 +242,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -242,7 +242,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -245,7 +245,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -293,7 +293,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -303,7 +303,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -298,7 +298,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -293,7 +293,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -298,7 +298,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -303,7 +303,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -303,7 +303,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -306,7 +306,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -306,7 +306,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -330,7 +330,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -354,7 +354,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -381,7 +381,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -384,7 +384,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -384,7 +384,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -401,7 +401,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -398,7 +398,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -384,7 +384,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -400,7 +400,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -412,7 +412,7 @@ namespace ProjectLighthouse.Migrations
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Token", b =>
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()

View file

@ -0,0 +1,654 @@
// <auto-generated />
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20211120045239_AddPasswordToUser")]
partial class AddPasswordToUser
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.Property<int>("HeartedProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("HeartedUserId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedProfileId");
b.HasIndex("HeartedUserId");
b.HasIndex("UserId");
b.ToTable("HeartedProfiles");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.Property<int>("HeartedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("HeartedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.Property<int>("QueuedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("QueuedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("QueuedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.Property<int>("RatedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("Rating")
.HasColumnType("int");
b.Property<double>("RatingLBP1")
.HasColumnType("double");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("RatedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("RatedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.Property<int>("SlotId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AuthorLabels")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("BackgroundHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("FirstUploaded")
.HasColumnType("bigint");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<string>("IconHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("InitiallyLocked")
.HasColumnType("tinyint(1)");
b.Property<long>("LastUpdated")
.HasColumnType("bigint");
b.Property<bool>("Lbp1Only")
.HasColumnType("tinyint(1)");
b.Property<string>("LevelType")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<int>("MaximumPlayers")
.HasColumnType("int");
b.Property<int>("MinimumPlayers")
.HasColumnType("int");
b.Property<bool>("MoveRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaComplete")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaUnique")
.HasColumnType("int");
b.Property<string>("ResourceCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("RootLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Shareable")
.HasColumnType("int");
b.Property<bool>("SubLevel")
.HasColumnType("tinyint(1)");
b.Property<bool>("TeamPick")
.HasColumnType("tinyint(1)");
b.HasKey("SlotId");
b.HasIndex("CreatorId");
b.HasIndex("LocationId");
b.ToTable("Slots");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.Property<int>("VisitedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("VisitedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("VisitedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.Property<int>("PhotoId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("LargeHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MediumHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PhotoSubjectCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PlanHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("SmallHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("PhotoId");
b.HasIndex("CreatorId");
b.ToTable("Photos");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.Property<int>("PhotoSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Bounds")
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("PhotoSubjectId");
b.HasIndex("UserId");
b.ToTable("PhotoSubjects");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.Property<int>("CommentId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<int>("PosterUserId")
.HasColumnType("int");
b.Property<int>("TargetUserId")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("CommentId");
b.HasIndex("PosterUserId");
b.HasIndex("TargetUserId");
b.ToTable("Comments");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("UserId");
b.ToTable("LastMatches");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("X")
.HasColumnType("int");
b.Property<int>("Y")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.Property<int>("ScoreId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("PlayerIdCollection")
.HasColumnType("longtext");
b.Property<int>("Points")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("ScoreId");
b.HasIndex("SlotId");
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserLocation")
.HasColumnType("longtext");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("Tokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Biography")
.HasColumnType("longtext");
b.Property<int>("Game")
.HasColumnType("int");
b.Property<string>("IconHash")
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<string>("Password")
.HasColumnType("longtext");
b.Property<string>("Pins")
.HasColumnType("longtext");
b.Property<string>("PlanetHash")
.HasColumnType("longtext");
b.Property<string>("Username")
.HasColumnType("longtext");
b.HasKey("UserId");
b.HasIndex("LocationId");
b.ToTable("Users");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
.WithMany()
.HasForeignKey("HeartedUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("HeartedUser");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
b.Navigation("Location");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
.WithMany()
.HasForeignKey("PosterUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
.WithMany()
.HasForeignKey("TargetUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Poster");
b.Navigation("Target");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Location");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
public partial class AddPasswordToUser : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Password",
table: "Users",
type: "longtext",
nullable: true)
.Annotation("MySql:CharSet", "utf8mb4");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Password",
table: "Users");
}
}
}

View file

@ -0,0 +1,654 @@
// <auto-generated />
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20211120052549_RenameTokensToGameTokens")]
partial class RenameTokensToGameTokens
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserLocation")
.HasColumnType("longtext");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("GameTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.Property<int>("HeartedProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("HeartedUserId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedProfileId");
b.HasIndex("HeartedUserId");
b.HasIndex("UserId");
b.ToTable("HeartedProfiles");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.Property<int>("HeartedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("HeartedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.Property<int>("QueuedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("QueuedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("QueuedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.Property<int>("RatedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("Rating")
.HasColumnType("int");
b.Property<double>("RatingLBP1")
.HasColumnType("double");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("RatedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("RatedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.Property<int>("SlotId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AuthorLabels")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("BackgroundHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("FirstUploaded")
.HasColumnType("bigint");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<string>("IconHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("InitiallyLocked")
.HasColumnType("tinyint(1)");
b.Property<long>("LastUpdated")
.HasColumnType("bigint");
b.Property<bool>("Lbp1Only")
.HasColumnType("tinyint(1)");
b.Property<string>("LevelType")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<int>("MaximumPlayers")
.HasColumnType("int");
b.Property<int>("MinimumPlayers")
.HasColumnType("int");
b.Property<bool>("MoveRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaComplete")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaUnique")
.HasColumnType("int");
b.Property<string>("ResourceCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("RootLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Shareable")
.HasColumnType("int");
b.Property<bool>("SubLevel")
.HasColumnType("tinyint(1)");
b.Property<bool>("TeamPick")
.HasColumnType("tinyint(1)");
b.HasKey("SlotId");
b.HasIndex("CreatorId");
b.HasIndex("LocationId");
b.ToTable("Slots");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.Property<int>("VisitedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("VisitedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("VisitedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.Property<int>("PhotoId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("LargeHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MediumHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PhotoSubjectCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PlanHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("SmallHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("PhotoId");
b.HasIndex("CreatorId");
b.ToTable("Photos");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.Property<int>("PhotoSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Bounds")
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("PhotoSubjectId");
b.HasIndex("UserId");
b.ToTable("PhotoSubjects");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.Property<int>("CommentId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<int>("PosterUserId")
.HasColumnType("int");
b.Property<int>("TargetUserId")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("CommentId");
b.HasIndex("PosterUserId");
b.HasIndex("TargetUserId");
b.ToTable("Comments");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("UserId");
b.ToTable("LastMatches");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("X")
.HasColumnType("int");
b.Property<int>("Y")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.Property<int>("ScoreId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("PlayerIdCollection")
.HasColumnType("longtext");
b.Property<int>("Points")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("ScoreId");
b.HasIndex("SlotId");
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Biography")
.HasColumnType("longtext");
b.Property<int>("Game")
.HasColumnType("int");
b.Property<string>("IconHash")
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<string>("Password")
.HasColumnType("longtext");
b.Property<string>("Pins")
.HasColumnType("longtext");
b.Property<string>("PlanetHash")
.HasColumnType("longtext");
b.Property<string>("Username")
.HasColumnType("longtext");
b.HasKey("UserId");
b.HasIndex("LocationId");
b.ToTable("Users");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
.WithMany()
.HasForeignKey("HeartedUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("HeartedUser");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
b.Navigation("Location");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
.WithMany()
.HasForeignKey("PosterUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
.WithMany()
.HasForeignKey("TargetUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Poster");
b.Navigation("Target");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Location");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,41 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
public partial class RenameTokensToGameTokens : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_Tokens",
table: "Tokens");
migrationBuilder.RenameTable(
name: "Tokens",
newName: "GameTokens");
migrationBuilder.AddPrimaryKey(
name: "PK_GameTokens",
table: "GameTokens",
column: "TokenId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_GameTokens",
table: "GameTokens");
migrationBuilder.RenameTable(
name: "GameTokens",
newName: "Tokens");
migrationBuilder.AddPrimaryKey(
name: "PK_Tokens",
table: "Tokens",
column: "TokenId");
}
}
}

View file

@ -0,0 +1,671 @@
// <auto-generated />
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20211120053654_AddWebTokens")]
partial class AddWebTokens
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserLocation")
.HasColumnType("longtext");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("GameTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.Property<int>("HeartedProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("HeartedUserId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedProfileId");
b.HasIndex("HeartedUserId");
b.HasIndex("UserId");
b.ToTable("HeartedProfiles");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.Property<int>("HeartedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("HeartedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.Property<int>("QueuedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("QueuedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("QueuedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.Property<int>("RatedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("Rating")
.HasColumnType("int");
b.Property<double>("RatingLBP1")
.HasColumnType("double");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("RatedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("RatedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.Property<int>("SlotId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AuthorLabels")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("BackgroundHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("FirstUploaded")
.HasColumnType("bigint");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<string>("IconHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("InitiallyLocked")
.HasColumnType("tinyint(1)");
b.Property<long>("LastUpdated")
.HasColumnType("bigint");
b.Property<bool>("Lbp1Only")
.HasColumnType("tinyint(1)");
b.Property<string>("LevelType")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<int>("MaximumPlayers")
.HasColumnType("int");
b.Property<int>("MinimumPlayers")
.HasColumnType("int");
b.Property<bool>("MoveRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaComplete")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaUnique")
.HasColumnType("int");
b.Property<string>("ResourceCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("RootLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Shareable")
.HasColumnType("int");
b.Property<bool>("SubLevel")
.HasColumnType("tinyint(1)");
b.Property<bool>("TeamPick")
.HasColumnType("tinyint(1)");
b.HasKey("SlotId");
b.HasIndex("CreatorId");
b.HasIndex("LocationId");
b.ToTable("Slots");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.Property<int>("VisitedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("VisitedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("VisitedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.Property<int>("PhotoId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("LargeHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MediumHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PhotoSubjectCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PlanHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("SmallHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("PhotoId");
b.HasIndex("CreatorId");
b.ToTable("Photos");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.Property<int>("PhotoSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Bounds")
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("PhotoSubjectId");
b.HasIndex("UserId");
b.ToTable("PhotoSubjects");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.Property<int>("CommentId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<int>("PosterUserId")
.HasColumnType("int");
b.Property<int>("TargetUserId")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("CommentId");
b.HasIndex("PosterUserId");
b.HasIndex("TargetUserId");
b.ToTable("Comments");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("UserId");
b.ToTable("LastMatches");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("X")
.HasColumnType("int");
b.Property<int>("Y")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.Property<int>("ScoreId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("PlayerIdCollection")
.HasColumnType("longtext");
b.Property<int>("Points")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("ScoreId");
b.HasIndex("SlotId");
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Biography")
.HasColumnType("longtext");
b.Property<int>("Game")
.HasColumnType("int");
b.Property<string>("IconHash")
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<string>("Password")
.HasColumnType("longtext");
b.Property<string>("Pins")
.HasColumnType("longtext");
b.Property<string>("PlanetHash")
.HasColumnType("longtext");
b.Property<string>("Username")
.HasColumnType("longtext");
b.HasKey("UserId");
b.HasIndex("LocationId");
b.ToTable("Users");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.WebToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("WebTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
.WithMany()
.HasForeignKey("HeartedUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("HeartedUser");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
b.Navigation("Location");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
.WithMany()
.HasForeignKey("PosterUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
.WithMany()
.HasForeignKey("TargetUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Poster");
b.Navigation("Target");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Location");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,35 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
public partial class AddWebTokens : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "WebTokens",
columns: table => new
{
TokenId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
UserId = table.Column<int>(type: "int", nullable: false),
UserToken = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_WebTokens", x => x.TokenId);
})
.Annotation("MySql:CharSet", "utf8mb4");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "WebTokens");
}
}
}

View file

@ -0,0 +1,710 @@
// <auto-generated />
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20211122002000_AddAuthenticationAttempts")]
partial class AddAuthenticationAttempts
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
{
b.Property<int>("AuthenticationAttemptId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameTokenId")
.HasColumnType("int");
b.Property<string>("IPAddress")
.HasColumnType("longtext");
b.Property<int>("Platform")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("AuthenticationAttemptId");
b.HasIndex("GameTokenId");
b.ToTable("AuthenticationAttempts");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<bool>("Approved")
.HasColumnType("tinyint(1)");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserLocation")
.HasColumnType("longtext");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("GameTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.Property<int>("HeartedProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("HeartedUserId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedProfileId");
b.HasIndex("HeartedUserId");
b.HasIndex("UserId");
b.ToTable("HeartedProfiles");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.Property<int>("HeartedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("HeartedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.Property<int>("QueuedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("QueuedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("QueuedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.Property<int>("RatedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("Rating")
.HasColumnType("int");
b.Property<double>("RatingLBP1")
.HasColumnType("double");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("RatedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("RatedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.Property<int>("SlotId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AuthorLabels")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("BackgroundHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("FirstUploaded")
.HasColumnType("bigint");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<string>("IconHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("InitiallyLocked")
.HasColumnType("tinyint(1)");
b.Property<long>("LastUpdated")
.HasColumnType("bigint");
b.Property<bool>("Lbp1Only")
.HasColumnType("tinyint(1)");
b.Property<string>("LevelType")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<int>("MaximumPlayers")
.HasColumnType("int");
b.Property<int>("MinimumPlayers")
.HasColumnType("int");
b.Property<bool>("MoveRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaComplete")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaUnique")
.HasColumnType("int");
b.Property<string>("ResourceCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("RootLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Shareable")
.HasColumnType("int");
b.Property<bool>("SubLevel")
.HasColumnType("tinyint(1)");
b.Property<bool>("TeamPick")
.HasColumnType("tinyint(1)");
b.HasKey("SlotId");
b.HasIndex("CreatorId");
b.HasIndex("LocationId");
b.ToTable("Slots");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.Property<int>("VisitedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("VisitedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("VisitedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.Property<int>("PhotoId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("LargeHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MediumHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PhotoSubjectCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PlanHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("SmallHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("PhotoId");
b.HasIndex("CreatorId");
b.ToTable("Photos");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.Property<int>("PhotoSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Bounds")
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("PhotoSubjectId");
b.HasIndex("UserId");
b.ToTable("PhotoSubjects");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.Property<int>("CommentId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<int>("PosterUserId")
.HasColumnType("int");
b.Property<int>("TargetUserId")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("CommentId");
b.HasIndex("PosterUserId");
b.HasIndex("TargetUserId");
b.ToTable("Comments");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("UserId");
b.ToTable("LastMatches");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("X")
.HasColumnType("int");
b.Property<int>("Y")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.Property<int>("ScoreId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("PlayerIdCollection")
.HasColumnType("longtext");
b.Property<int>("Points")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("ScoreId");
b.HasIndex("SlotId");
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Biography")
.HasColumnType("longtext");
b.Property<int>("Game")
.HasColumnType("int");
b.Property<string>("IconHash")
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<string>("Password")
.HasColumnType("longtext");
b.Property<string>("Pins")
.HasColumnType("longtext");
b.Property<string>("PlanetHash")
.HasColumnType("longtext");
b.Property<string>("Username")
.HasColumnType("longtext");
b.HasKey("UserId");
b.HasIndex("LocationId");
b.ToTable("Users");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.WebToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("WebTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.GameToken", "GameToken")
.WithMany()
.HasForeignKey("GameTokenId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("GameToken");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
.WithMany()
.HasForeignKey("HeartedUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("HeartedUser");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
b.Navigation("Location");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
.WithMany()
.HasForeignKey("PosterUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
.WithMany()
.HasForeignKey("TargetUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Poster");
b.Navigation("Target");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Location");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,59 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
public partial class AddAuthenticationAttempts : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "Approved",
table: "GameTokens",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
migrationBuilder.CreateTable(
name: "AuthenticationAttempts",
columns: table => new
{
AuthenticationAttemptId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Timestamp = table.Column<long>(type: "bigint", nullable: false),
Platform = table.Column<int>(type: "int", nullable: false),
IPAddress = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
GameTokenId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AuthenticationAttempts", x => x.AuthenticationAttemptId);
table.ForeignKey(
name: "FK_AuthenticationAttempts_GameTokens_GameTokenId",
column: x => x.GameTokenId,
principalTable: "GameTokens",
principalColumn: "TokenId",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_AuthenticationAttempts_GameTokenId",
table: "AuthenticationAttempts",
column: "GameTokenId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AuthenticationAttempts");
migrationBuilder.DropColumn(
name: "Approved",
table: "GameTokens");
}
}
}

View file

@ -0,0 +1,713 @@
// <auto-generated />
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20211123224001_AddIsAdminToUser")]
partial class AddIsAdminToUser
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
{
b.Property<int>("AuthenticationAttemptId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameTokenId")
.HasColumnType("int");
b.Property<string>("IPAddress")
.HasColumnType("longtext");
b.Property<int>("Platform")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("AuthenticationAttemptId");
b.HasIndex("GameTokenId");
b.ToTable("AuthenticationAttempts");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<bool>("Approved")
.HasColumnType("tinyint(1)");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserLocation")
.HasColumnType("longtext");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("GameTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.Property<int>("HeartedProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("HeartedUserId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedProfileId");
b.HasIndex("HeartedUserId");
b.HasIndex("UserId");
b.ToTable("HeartedProfiles");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.Property<int>("HeartedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("HeartedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.Property<int>("QueuedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("QueuedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("QueuedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.Property<int>("RatedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("Rating")
.HasColumnType("int");
b.Property<double>("RatingLBP1")
.HasColumnType("double");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("RatedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("RatedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.Property<int>("SlotId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AuthorLabels")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("BackgroundHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("FirstUploaded")
.HasColumnType("bigint");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<string>("IconHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("InitiallyLocked")
.HasColumnType("tinyint(1)");
b.Property<long>("LastUpdated")
.HasColumnType("bigint");
b.Property<bool>("Lbp1Only")
.HasColumnType("tinyint(1)");
b.Property<string>("LevelType")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<int>("MaximumPlayers")
.HasColumnType("int");
b.Property<int>("MinimumPlayers")
.HasColumnType("int");
b.Property<bool>("MoveRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaComplete")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaUnique")
.HasColumnType("int");
b.Property<string>("ResourceCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("RootLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Shareable")
.HasColumnType("int");
b.Property<bool>("SubLevel")
.HasColumnType("tinyint(1)");
b.Property<bool>("TeamPick")
.HasColumnType("tinyint(1)");
b.HasKey("SlotId");
b.HasIndex("CreatorId");
b.HasIndex("LocationId");
b.ToTable("Slots");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.Property<int>("VisitedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("VisitedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("VisitedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.Property<int>("PhotoId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("LargeHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MediumHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PhotoSubjectCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PlanHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("SmallHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("PhotoId");
b.HasIndex("CreatorId");
b.ToTable("Photos");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.Property<int>("PhotoSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Bounds")
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("PhotoSubjectId");
b.HasIndex("UserId");
b.ToTable("PhotoSubjects");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.Property<int>("CommentId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<int>("PosterUserId")
.HasColumnType("int");
b.Property<int>("TargetUserId")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("CommentId");
b.HasIndex("PosterUserId");
b.HasIndex("TargetUserId");
b.ToTable("Comments");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("UserId");
b.ToTable("LastMatches");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("X")
.HasColumnType("int");
b.Property<int>("Y")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.Property<int>("ScoreId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("PlayerIdCollection")
.HasColumnType("longtext");
b.Property<int>("Points")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("ScoreId");
b.HasIndex("SlotId");
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Biography")
.HasColumnType("longtext");
b.Property<int>("Game")
.HasColumnType("int");
b.Property<string>("IconHash")
.HasColumnType("longtext");
b.Property<bool>("IsAdmin")
.HasColumnType("tinyint(1)");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<string>("Password")
.HasColumnType("longtext");
b.Property<string>("Pins")
.HasColumnType("longtext");
b.Property<string>("PlanetHash")
.HasColumnType("longtext");
b.Property<string>("Username")
.HasColumnType("longtext");
b.HasKey("UserId");
b.HasIndex("LocationId");
b.ToTable("Users");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.WebToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("WebTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.GameToken", "GameToken")
.WithMany()
.HasForeignKey("GameTokenId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("GameToken");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
.WithMany()
.HasForeignKey("HeartedUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("HeartedUser");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
b.Navigation("Location");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
.WithMany()
.HasForeignKey("PosterUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
.WithMany()
.HasForeignKey("TargetUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Poster");
b.Navigation("Target");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Location");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
public partial class AddIsAdminToUser : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsAdmin",
table: "Users",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsAdmin",
table: "Users");
}
}
}

View file

@ -0,0 +1,716 @@
// <auto-generated />
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20211125052035_AddGameVersionToLastMatch")]
partial class AddGameVersionToLastMatch
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
{
b.Property<int>("AuthenticationAttemptId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameTokenId")
.HasColumnType("int");
b.Property<string>("IPAddress")
.HasColumnType("longtext");
b.Property<int>("Platform")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("AuthenticationAttemptId");
b.HasIndex("GameTokenId");
b.ToTable("AuthenticationAttempts");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<bool>("Approved")
.HasColumnType("tinyint(1)");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserLocation")
.HasColumnType("longtext");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("GameTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.Property<int>("HeartedProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("HeartedUserId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedProfileId");
b.HasIndex("HeartedUserId");
b.HasIndex("UserId");
b.ToTable("HeartedProfiles");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.Property<int>("HeartedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("HeartedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.Property<int>("QueuedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("QueuedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("QueuedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.Property<int>("RatedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("Rating")
.HasColumnType("int");
b.Property<double>("RatingLBP1")
.HasColumnType("double");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("RatedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("RatedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.Property<int>("SlotId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AuthorLabels")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("BackgroundHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("FirstUploaded")
.HasColumnType("bigint");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<string>("IconHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("InitiallyLocked")
.HasColumnType("tinyint(1)");
b.Property<long>("LastUpdated")
.HasColumnType("bigint");
b.Property<bool>("Lbp1Only")
.HasColumnType("tinyint(1)");
b.Property<string>("LevelType")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<int>("MaximumPlayers")
.HasColumnType("int");
b.Property<int>("MinimumPlayers")
.HasColumnType("int");
b.Property<bool>("MoveRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaComplete")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaUnique")
.HasColumnType("int");
b.Property<string>("ResourceCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("RootLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Shareable")
.HasColumnType("int");
b.Property<bool>("SubLevel")
.HasColumnType("tinyint(1)");
b.Property<bool>("TeamPick")
.HasColumnType("tinyint(1)");
b.HasKey("SlotId");
b.HasIndex("CreatorId");
b.HasIndex("LocationId");
b.ToTable("Slots");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.Property<int>("VisitedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("VisitedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("VisitedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.Property<int>("PhotoId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("LargeHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MediumHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PhotoSubjectCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PlanHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("SmallHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("PhotoId");
b.HasIndex("CreatorId");
b.ToTable("Photos");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.Property<int>("PhotoSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Bounds")
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("PhotoSubjectId");
b.HasIndex("UserId");
b.ToTable("PhotoSubjects");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.Property<int>("CommentId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<int>("PosterUserId")
.HasColumnType("int");
b.Property<int>("TargetUserId")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("CommentId");
b.HasIndex("PosterUserId");
b.HasIndex("TargetUserId");
b.ToTable("Comments");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("UserId");
b.ToTable("LastMatches");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("X")
.HasColumnType("int");
b.Property<int>("Y")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.Property<int>("ScoreId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("PlayerIdCollection")
.HasColumnType("longtext");
b.Property<int>("Points")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("ScoreId");
b.HasIndex("SlotId");
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Biography")
.HasColumnType("longtext");
b.Property<int>("Game")
.HasColumnType("int");
b.Property<string>("IconHash")
.HasColumnType("longtext");
b.Property<bool>("IsAdmin")
.HasColumnType("tinyint(1)");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<string>("Password")
.HasColumnType("longtext");
b.Property<string>("Pins")
.HasColumnType("longtext");
b.Property<string>("PlanetHash")
.HasColumnType("longtext");
b.Property<string>("Username")
.HasColumnType("longtext");
b.HasKey("UserId");
b.HasIndex("LocationId");
b.ToTable("Users");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.WebToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("WebTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.GameToken", "GameToken")
.WithMany()
.HasForeignKey("GameTokenId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("GameToken");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
.WithMany()
.HasForeignKey("HeartedUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("HeartedUser");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
b.Navigation("Location");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
.WithMany()
.HasForeignKey("PosterUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
.WithMany()
.HasForeignKey("TargetUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Poster");
b.Navigation("Target");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Location");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
public partial class AddGameVersionToLastMatch : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "GameVersion",
table: "LastMatches",
type: "int",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "GameVersion",
table: "LastMatches");
}
}
}

View file

@ -0,0 +1,719 @@
// <auto-generated />
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20211127201738_AddPasswordResetRequiredToUser")]
partial class AddPasswordResetRequiredToUser
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
{
b.Property<int>("AuthenticationAttemptId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameTokenId")
.HasColumnType("int");
b.Property<string>("IPAddress")
.HasColumnType("longtext");
b.Property<int>("Platform")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("AuthenticationAttemptId");
b.HasIndex("GameTokenId");
b.ToTable("AuthenticationAttempts");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<bool>("Approved")
.HasColumnType("tinyint(1)");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserLocation")
.HasColumnType("longtext");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("GameTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.Property<int>("HeartedProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("HeartedUserId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedProfileId");
b.HasIndex("HeartedUserId");
b.HasIndex("UserId");
b.ToTable("HeartedProfiles");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.Property<int>("HeartedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("HeartedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("HeartedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.Property<int>("QueuedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("QueuedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("QueuedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.Property<int>("RatedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("Rating")
.HasColumnType("int");
b.Property<double>("RatingLBP1")
.HasColumnType("double");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("RatedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("RatedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.Property<int>("SlotId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AuthorLabels")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("BackgroundHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("FirstUploaded")
.HasColumnType("bigint");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<string>("IconHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("InitiallyLocked")
.HasColumnType("tinyint(1)");
b.Property<long>("LastUpdated")
.HasColumnType("bigint");
b.Property<bool>("Lbp1Only")
.HasColumnType("tinyint(1)");
b.Property<string>("LevelType")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<int>("MaximumPlayers")
.HasColumnType("int");
b.Property<int>("MinimumPlayers")
.HasColumnType("int");
b.Property<bool>("MoveRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP1Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP2Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Complete")
.HasColumnType("int");
b.Property<int>("PlaysLBP3Unique")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaComplete")
.HasColumnType("int");
b.Property<int>("PlaysLBPVitaUnique")
.HasColumnType("int");
b.Property<string>("ResourceCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("RootLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Shareable")
.HasColumnType("int");
b.Property<bool>("SubLevel")
.HasColumnType("tinyint(1)");
b.Property<bool>("TeamPick")
.HasColumnType("tinyint(1)");
b.HasKey("SlotId");
b.HasIndex("CreatorId");
b.HasIndex("LocationId");
b.ToTable("Slots");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.Property<int>("VisitedLevelId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("PlaysLBP1")
.HasColumnType("int");
b.Property<int>("PlaysLBP2")
.HasColumnType("int");
b.Property<int>("PlaysLBP3")
.HasColumnType("int");
b.Property<int>("PlaysLBPVita")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("VisitedLevelId");
b.HasIndex("SlotId");
b.HasIndex("UserId");
b.ToTable("VisitedLevels");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.Property<int>("PhotoId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("LargeHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MediumHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PhotoSubjectCollection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("PlanHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("SmallHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("PhotoId");
b.HasIndex("CreatorId");
b.ToTable("Photos");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.Property<int>("PhotoSubjectId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Bounds")
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("PhotoSubjectId");
b.HasIndex("UserId");
b.ToTable("PhotoSubjects");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.Property<int>("CommentId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<int>("PosterUserId")
.HasColumnType("int");
b.Property<int>("TargetUserId")
.HasColumnType("int");
b.Property<int>("ThumbsDown")
.HasColumnType("int");
b.Property<int>("ThumbsUp")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("CommentId");
b.HasIndex("PosterUserId");
b.HasIndex("TargetUserId");
b.ToTable("Comments");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("GameVersion")
.HasColumnType("int");
b.Property<long>("Timestamp")
.HasColumnType("bigint");
b.HasKey("UserId");
b.ToTable("LastMatches");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("X")
.HasColumnType("int");
b.Property<int>("Y")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Locations");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.Property<int>("ScoreId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("PlayerIdCollection")
.HasColumnType("longtext");
b.Property<int>("Points")
.HasColumnType("int");
b.Property<int>("SlotId")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("ScoreId");
b.HasIndex("SlotId");
b.ToTable("Scores");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Biography")
.HasColumnType("longtext");
b.Property<int>("Game")
.HasColumnType("int");
b.Property<string>("IconHash")
.HasColumnType("longtext");
b.Property<bool>("IsAdmin")
.HasColumnType("tinyint(1)");
b.Property<int>("LocationId")
.HasColumnType("int");
b.Property<string>("Password")
.HasColumnType("longtext");
b.Property<bool>("PasswordResetRequired")
.HasColumnType("tinyint(1)");
b.Property<string>("Pins")
.HasColumnType("longtext");
b.Property<string>("PlanetHash")
.HasColumnType("longtext");
b.Property<string>("Username")
.HasColumnType("longtext");
b.HasKey("UserId");
b.HasIndex("LocationId");
b.ToTable("Users");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.WebToken", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.Property<string>("UserToken")
.HasColumnType("longtext");
b.HasKey("TokenId");
b.ToTable("WebTokens");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.GameToken", "GameToken")
.WithMany()
.HasForeignKey("GameTokenId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("GameToken");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
.WithMany()
.HasForeignKey("HeartedUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("HeartedUser");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
b.Navigation("Location");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator")
.WithMany()
.HasForeignKey("CreatorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Creator");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster")
.WithMany()
.HasForeignKey("PosterUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target")
.WithMany()
.HasForeignKey("TargetUserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Poster");
b.Navigation("Target");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot")
.WithMany()
.HasForeignKey("SlotId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Slot");
});
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b =>
{
b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location")
.WithMany()
.HasForeignKey("LocationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Location");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
public partial class AddPasswordResetRequiredToUser : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "PasswordResetRequired",
table: "Users",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PasswordResetRequired",
table: "Users");
}
}
}

Some files were not shown because too many files have changed in this diff Show more