diff --git a/ProjectLighthouse/Controllers/CommentController.cs b/ProjectLighthouse/Controllers/CommentController.cs index 2bcb35d3..1b251917 100644 --- a/ProjectLighthouse/Controllers/CommentController.cs +++ b/ProjectLighthouse/Controllers/CommentController.cs @@ -13,11 +13,17 @@ namespace ProjectLighthouse.Controllers { [Route("LITTLEBIGPLANETPS3_XML/")] [Produces("text/xml")] public class CommentController : ControllerBase { + private readonly Database database; + public CommentController(Database database) { + this.database = database; + } + [HttpGet("userComments/{username}")] public async Task GetComments(string username) { - // the following is downright retarded, but its 12:48am and i do not give a shit - // ↓ ok... ↓ why does this need to be wrapped ↓ again???? whyyyy - List comments = (await new Database().Comments.ToListAsync()).Where(c => c.TargetUsername == username).ToList(); + List comments = await database.Comments + .Include(c => c.Target) + .Where(c => c.Target.Username == username) + .ToListAsync(); string outputXml = comments.Aggregate(string.Empty, (current, comment) => current + comment.Serialize()); return this.Ok(LbpSerializer.StringElement("comments", outputXml)); @@ -31,7 +37,6 @@ namespace ProjectLighthouse.Controllers { XmlSerializer serializer = new(typeof(Comment)); Comment comment = (Comment)serializer.Deserialize(new StringReader(bodyString)); - await using Database database = new(); User poster = await database.UserFromRequest(Request); if(poster == null) return this.StatusCode(403, ""); diff --git a/ProjectLighthouse/Controllers/LoginController.cs b/ProjectLighthouse/Controllers/LoginController.cs index 5b137aa4..5f0dd357 100644 --- a/ProjectLighthouse/Controllers/LoginController.cs +++ b/ProjectLighthouse/Controllers/LoginController.cs @@ -12,6 +12,12 @@ namespace ProjectLighthouse.Controllers { [Route("LITTLEBIGPLANETPS3_XML/login")] [Produces("text/xml")] public class LoginController : ControllerBase { + private readonly Database database; + + public LoginController(Database database) { + this.database = database; + } + [HttpPost] public async Task Login() { if(!this.Request.Query.TryGetValue("titleID", out StringValues _)) @@ -27,8 +33,6 @@ namespace ProjectLighthouse.Controllers { return this.BadRequest(); } - await using Database database = new(); - Token? token = await database.AuthenticateUser(loginData); if(token == null) return this.StatusCode(403, ""); diff --git a/ProjectLighthouse/Controllers/MessageController.cs b/ProjectLighthouse/Controllers/MessageController.cs index c6a4089c..1a6ac5c7 100644 --- a/ProjectLighthouse/Controllers/MessageController.cs +++ b/ProjectLighthouse/Controllers/MessageController.cs @@ -8,9 +8,14 @@ namespace ProjectLighthouse.Controllers { [Route("LITTLEBIGPLANETPS3_XML/")] [Produces("text/plain")] public class MessageController : ControllerBase { + private readonly Database database; + public MessageController(Database database) { + this.database = database; + } + [HttpGet("eula")] public async Task Eula() { - User user = await new Database().UserFromRequest(Request); + User user = await this.database.UserFromRequest(Request); return user == null ? this.StatusCode(403, "") : this.Ok($"You are logged in as user {user.Username} (id {user.UserId})"); } diff --git a/ProjectLighthouse/Controllers/PublishController.cs b/ProjectLighthouse/Controllers/PublishController.cs index 77d92c21..dd1fae0b 100644 --- a/ProjectLighthouse/Controllers/PublishController.cs +++ b/ProjectLighthouse/Controllers/PublishController.cs @@ -11,6 +11,12 @@ namespace ProjectLighthouse.Controllers { [Route("LITTLEBIGPLANETPS3_XML/")] [Produces("text/xml")] public class PublishController : ControllerBase { + private readonly Database database; + + public PublishController(Database database) { + this.database = database; + } + /// /// Endpoint the game uses to verify that the level is compatible (?) /// @@ -27,8 +33,6 @@ namespace ProjectLighthouse.Controllers { /// [HttpPost("publish")] public async Task Publish() { - await using Database database = new(); - User user = await database.UserFromRequest(Request); if(user == null) return this.StatusCode(403, ""); @@ -52,8 +56,6 @@ namespace ProjectLighthouse.Controllers { [HttpPost("unpublish/{id:int}")] public async Task Unpublish(int id) { - await using Database database = new(); - Slot slot = await database.Slots.FirstOrDefaultAsync(s => s.SlotId == id); database.Locations.Remove(slot.Location); diff --git a/ProjectLighthouse/Controllers/SlotsController.cs b/ProjectLighthouse/Controllers/SlotsController.cs index ba095e09..3f2735d9 100644 --- a/ProjectLighthouse/Controllers/SlotsController.cs +++ b/ProjectLighthouse/Controllers/SlotsController.cs @@ -10,23 +10,39 @@ namespace ProjectLighthouse.Controllers { [Route("LITTLEBIGPLANETPS3_XML/")] [Produces("text/xml")] public class SlotsController : ControllerBase { + private readonly Database database; + public SlotsController(Database database) { + this.database = database; + } + [HttpGet("slots/by")] public IActionResult SlotsBy() { - string response = Enumerable.Aggregate(new Database().Slots, string.Empty, (current, slot) => current + slot.Serialize()); + string response = Enumerable.Aggregate( + database.Slots + .Include(s => s.Creator) + .Include(s => s.Location) + , string.Empty, (current, slot) => current + slot.Serialize()); return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "total", 1)); } [HttpGet("s/user/{id:int}")] public async Task SUser(int id) { - Slot slot = await new Database().Slots.FirstOrDefaultAsync(s => s.SlotId == id); + Slot slot = await this.database.Slots + .Include(s => s.Creator) + .Include(s => s.Location) + .FirstOrDefaultAsync(s => s.SlotId == id); return this.Ok(slot.Serialize()); } [HttpGet("slots/lolcatftw/{username}")] public IActionResult SlotsLolCat(string username) { - string response = Enumerable.Aggregate(new Database().Slots, string.Empty, (current, slot) => current + slot.Serialize()); + string response = Enumerable.Aggregate( + database.Slots + .Include(s => s.Creator) + .Include(s => s.Location) + , string.Empty, (current, slot) => current + slot.Serialize()); return this.Ok(LbpSerializer.TaggedStringElement("slots", response, "total", 1)); } diff --git a/ProjectLighthouse/Controllers/UserController.cs b/ProjectLighthouse/Controllers/UserController.cs index 244cec20..baebd029 100644 --- a/ProjectLighthouse/Controllers/UserController.cs +++ b/ProjectLighthouse/Controllers/UserController.cs @@ -12,11 +12,16 @@ namespace ProjectLighthouse.Controllers { [Route("LITTLEBIGPLANETPS3_XML/")] [Produces("text/xml")] public class UserController : ControllerBase { + private readonly Database database; + public UserController(Database database) { + this.database = database; + } + [HttpGet("user/{username}")] public async Task GetUser(string username) { - await using Database database = new(); - - User user = await database.Users.FirstOrDefaultAsync(u => u.Username == username); + User user = await database.Users + .Include(u => u.Location) + .FirstOrDefaultAsync(u => u.Username == username); if(user == null) return this.NotFound(); return this.Ok(user.Serialize()); @@ -30,7 +35,6 @@ namespace ProjectLighthouse.Controllers { [HttpPost("updateUser")] public async Task UpdateUser() { - await using Database database = new(); User user = await database.UserFromRequest(Request); if(user == null) return this.StatusCode(403, ""); diff --git a/ProjectLighthouse/Database.cs b/ProjectLighthouse/Database.cs index ce078a7e..4e702974 100644 --- a/ProjectLighthouse/Database.cs +++ b/ProjectLighthouse/Database.cs @@ -13,12 +13,12 @@ namespace ProjectLighthouse { public DbSet Slots { get; set; } public DbSet Comments { get; set; } public DbSet Tokens { get; set; } - + protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql( ServerSettings.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion ); - + public async Task CreateUser(string username) { Location l = new(); // store to get id after submitting this.Locations.Add(l); // add to table @@ -60,7 +60,9 @@ namespace ProjectLighthouse { public async Task UserFromAuthToken(string authToken) { Token? token = await Tokens.FirstOrDefaultAsync(t => t.UserToken == authToken); if(token == null) return null; - return await Users.FirstOrDefaultAsync(u => u.UserId == token.UserId); + return await Users + .Include(u => u.Location) + .FirstOrDefaultAsync(u => u.UserId == token.UserId); } public async Task UserFromRequest(HttpRequest request) { diff --git a/ProjectLighthouse/Program.cs b/ProjectLighthouse/Program.cs index d79c24ac..3e74c1f7 100644 --- a/ProjectLighthouse/Program.cs +++ b/ProjectLighthouse/Program.cs @@ -1,5 +1,7 @@ using System; using Microsoft.AspNetCore.Hosting; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using ProjectLighthouse.Types; @@ -9,13 +11,13 @@ namespace ProjectLighthouse { Console.WriteLine("Welcome to Project Lighthouse!"); Console.WriteLine(ServerSettings.DbConnected ? "Connected to the database." : "Database unavailable. Starting in stateless mode."); - CreateHostBuilder(args).Build().Run(); - } + IHostBuilder builder = Host.CreateDefaultBuilder(args); + + builder.ConfigureWebHostDefaults(webBuilder => { + webBuilder.UseStartup(); + }); - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => { - webBuilder.UseStartup(); - }); + builder.Build().Run(); + } } } \ No newline at end of file diff --git a/ProjectLighthouse/ProjectLighthouse.csproj b/ProjectLighthouse/ProjectLighthouse.csproj index 64633e26..18ab9cbb 100644 --- a/ProjectLighthouse/ProjectLighthouse.csproj +++ b/ProjectLighthouse/ProjectLighthouse.csproj @@ -7,7 +7,8 @@ - + + diff --git a/ProjectLighthouse/Startup.cs b/ProjectLighthouse/Startup.cs index 173c5caf..b9e9b518 100644 --- a/ProjectLighthouse/Startup.cs +++ b/ProjectLighthouse/Startup.cs @@ -3,10 +3,12 @@ using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using ProjectLighthouse.Serialization; +using ProjectLighthouse.Types; namespace ProjectLighthouse { public class Startup { @@ -18,10 +20,11 @@ namespace ProjectLighthouse { // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.AddControllers(); services.AddMvc(options => options.OutputFormatters.Add(new XmlOutputFormatter())); + + services.AddDbContext(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/ProjectLighthouse/Types/Comment.cs b/ProjectLighthouse/Types/Comment.cs index 1faf6dda..d3abdec0 100644 --- a/ProjectLighthouse/Types/Comment.cs +++ b/ProjectLighthouse/Types/Comment.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Xml.Serialization; using ProjectLighthouse.Serialization; @@ -14,25 +15,11 @@ namespace ProjectLighthouse.Types { public int TargetUserId { get; set; } - private string posterUsername; - -// [XmlAttribute("username")] - public string PosterUsername { - get { - if(this.posterUsername != null) return this.posterUsername; - return this.posterUsername = new Database().Users.First(u => u.UserId == PosterUserId).Username; - } - } - - private string targetUsername; - - public string TargetUsername { - get { - if(this.targetUsername != null) return this.targetUsername; - - return this.targetUsername = new Database().Users.First(u => u.UserId == TargetUserId).Username; - } - } + [ForeignKey(nameof(PosterUserId))] + public User Poster { get; set; } + + [ForeignKey(nameof(TargetUserId))] + public User Target { get; set; } public long Timestamp { get; set; } @@ -43,7 +30,7 @@ namespace ProjectLighthouse.Types { private string serialize() { return LbpSerializer.StringElement("id", CommentId) + - LbpSerializer.StringElement("npHandle", this.PosterUsername) + + LbpSerializer.StringElement("npHandle", this.Poster.Username) + LbpSerializer.StringElement("timestamp", Timestamp) + LbpSerializer.StringElement("message", Message) + LbpSerializer.StringElement("thumbsup", ThumbsUp) + diff --git a/ProjectLighthouse/Types/Slot.cs b/ProjectLighthouse/Types/Slot.cs index 4d061dab..eb090eab 100644 --- a/ProjectLighthouse/Types/Slot.cs +++ b/ProjectLighthouse/Types/Slot.cs @@ -2,6 +2,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Xml.Serialization; +using Microsoft.EntityFrameworkCore.Metadata.Internal; using ProjectLighthouse.Serialization; namespace ProjectLighthouse.Types { @@ -39,30 +40,16 @@ namespace ProjectLighthouse.Types { [XmlIgnore] public int CreatorId { get; set; } - - private User creator; - public User Creator { - get { - if(this.creator != null) return this.creator; - - return creator = new Database().Users.First(u => u.UserId == CreatorId); - } - } - - private Location location; + [ForeignKey(nameof(CreatorId))] + public User Creator { get; set; } /// /// The location of the level on the creator's earth /// [XmlElement("location")] - public Location Location { - get { - if(location != null) return this.location; - - return location = new Database().Locations.First(l => l.Id == LocationId); - } - } + [ForeignKey(nameof(LocationId))] + public Location Location { get; set; } [XmlElement("initiallyLocked")] public bool InitiallyLocked { get; set; } diff --git a/ProjectLighthouse/Types/User.cs b/ProjectLighthouse/Types/User.cs index fdd5b037..0badffc0 100644 --- a/ProjectLighthouse/Types/User.cs +++ b/ProjectLighthouse/Types/User.cs @@ -1,3 +1,4 @@ +using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using ProjectLighthouse.Serialization; @@ -23,17 +24,12 @@ namespace ProjectLighthouse.Types { public bool CommentsEnabled { get; set; } public int LocationId { get; set; } - - private Location location; + /// /// The location of the profile card on the user's earth /// - public Location Location { - get { - if(location != null) return this.location; - return location = new Database().Locations.First(l => l.Id == LocationId); - } - } + [ForeignKey("LocationId")] + public Location Location { get; set; } public int FavouriteSlotCount { get; set; } public int FavouriteUserCount { get; set; }