Init Commit
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
bin/
|
||||
obj/
|
||||
/packages/
|
||||
riderModule.iml
|
||||
/_ReSharper.Caches/
|
||||
13
.idea/.idea.DreamsCaster/.idea/.gitignore
generated
vendored
Normal file
13
.idea/.idea.DreamsCaster/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
/modules.xml
|
||||
/.idea.DreamsCaster.iml
|
||||
/contentModel.xml
|
||||
/projectSettingsUpdater.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
8
.idea/.idea.DreamsCaster/.idea/indexLayout.xml
generated
Normal file
8
.idea/.idea.DreamsCaster/.idea/indexLayout.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/.idea.DreamsCaster/.idea/vcs.xml
generated
Normal file
6
.idea/.idea.DreamsCaster/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
16
DreamsCaster.sln
Normal file
16
DreamsCaster.sln
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DreamsCaster", "DreamsCaster\DreamsCaster.csproj", "{7EF668EB-6D79-4A51-A161-F4E99DCCD789}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7EF668EB-6D79-4A51-A161-F4E99DCCD789}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7EF668EB-6D79-4A51-A161-F4E99DCCD789}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7EF668EB-6D79-4A51-A161-F4E99DCCD789}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7EF668EB-6D79-4A51-A161-F4E99DCCD789}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
25
DreamsCaster/.dockerignore
Normal file
25
DreamsCaster/.dockerignore
Normal file
@@ -0,0 +1,25 @@
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/.idea
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/azds.yaml
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
26
DreamsCaster/AppDbContext.cs
Normal file
26
DreamsCaster/AppDbContext.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using DreamsCaster.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Console = DreamsCaster.Models.Console;
|
||||
|
||||
namespace DreamsCaster;
|
||||
|
||||
public class AppDbContext : DbContext
|
||||
{
|
||||
public DbSet<Game> Games;
|
||||
public DbSet<Console> Consoles;
|
||||
}
|
||||
|
||||
public static class DatabaseExtensions
|
||||
{
|
||||
public static bool TryGet<T>(this IEnumerable<T> haystack, Guid id, out T val) where T : IdEntity
|
||||
{
|
||||
if (haystack.Select(hay => hay.Id).Contains(id))
|
||||
{
|
||||
val = haystack.FirstOrDefault(hay => hay.Id.Equals(id));
|
||||
return true;
|
||||
}
|
||||
|
||||
val = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
90
DreamsCaster/Controllers/ConsoleController.cs
Normal file
90
DreamsCaster/Controllers/ConsoleController.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using DreamsCaster.Helpers;
|
||||
using DreamsCaster.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Console = System.Console;
|
||||
|
||||
namespace DreamsCaster.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
public class ConsoleController : ControllerBase
|
||||
{
|
||||
public AppDbContext Database { get; set; }
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Get([FromQuery] Guid consoleId)
|
||||
{
|
||||
if (!Database.Consoles.TryGet(consoleId, out Game game)) return NotFound();
|
||||
|
||||
return Ok(game);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> DeleteAsync([FromQuery] Guid consoleId)
|
||||
{
|
||||
if (!Database.Games.TryGet(consoleId, out var game)) return NotFound();
|
||||
|
||||
foreach (var release in game.Releases)
|
||||
{
|
||||
Database.Remove(release);
|
||||
}
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
Database.Games.Remove(game);
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPatch]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> PatchAsync([FromQuery] Guid consoleId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> PostAsync([FromBody] PostGame newGame)
|
||||
{
|
||||
try
|
||||
{
|
||||
var game = Database.Games.Add(new Game()
|
||||
{
|
||||
Name = newGame.Name,
|
||||
Data = new MetaData<Game>()
|
||||
{
|
||||
CoverPhoto = newGame.CoverPhoto,
|
||||
Description = newGame.Description
|
||||
}
|
||||
});
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
foreach (var release in newGame.Releases)
|
||||
{
|
||||
if (!Database.Consoles.TryGet(release.ConsoleId, out var console)) continue;
|
||||
|
||||
game.Entity.Releases.Add(new Release()
|
||||
{
|
||||
ReleaseDate = release.Release,
|
||||
Console = console
|
||||
});
|
||||
}
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
return Ok(game);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
}
|
||||
192
DreamsCaster/Controllers/GameController.cs
Normal file
192
DreamsCaster/Controllers/GameController.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using DreamsCaster.Helpers;
|
||||
using DreamsCaster.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Console = System.Console;
|
||||
|
||||
namespace DreamsCaster.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
public class GameController : ControllerBase
|
||||
{
|
||||
public class PostRelease
|
||||
{
|
||||
public DateTime Release;
|
||||
public Guid ConsoleId;
|
||||
}
|
||||
|
||||
public class PostGame
|
||||
{
|
||||
public string Name;
|
||||
public string Description;
|
||||
public string CoverPhoto;
|
||||
|
||||
public List<PostRelease> Releases;
|
||||
}
|
||||
|
||||
public class PatchGame
|
||||
{
|
||||
public Optional<string> Name;
|
||||
public Optional<string> Description;
|
||||
public Optional<string> CoverPhoto;
|
||||
}
|
||||
|
||||
public AppDbContext Database { get; set; }
|
||||
|
||||
#region Game CRUD
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Get([FromQuery] Guid gameId)
|
||||
{
|
||||
if (!Database.Games.TryGet(gameId, out Game game)) return NotFound();
|
||||
|
||||
return Ok(game);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> DeleteAsync([FromQuery] Guid gameId)
|
||||
{
|
||||
if (!Database.Games.TryGet(gameId, out var game)) return NotFound();
|
||||
|
||||
foreach (var release in game.Releases)
|
||||
{
|
||||
Database.Remove(release);
|
||||
}
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
Database.Games.Remove(game);
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpPatch]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> PatchAsync([FromQuery] Guid gameId, [FromBody] PatchGame newData)
|
||||
{
|
||||
if (!Database.Games.TryGet(gameId, out Game game)) return NotFound();
|
||||
|
||||
if (newData.Name.HasValue) game.Name = newData.Name;
|
||||
if (newData.Description.HasValue) game.Data.Description = newData.Description;
|
||||
if (newData.CoverPhoto.HasValue) game.Data.CoverPhoto = newData.CoverPhoto;
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
return Ok(game);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> PostAsync([FromBody] PostGame newGame)
|
||||
{
|
||||
try
|
||||
{
|
||||
var game = Database.Games.Add(new Game()
|
||||
{
|
||||
Name = newGame.Name,
|
||||
Data = new MetaData<Game>()
|
||||
{
|
||||
CoverPhoto = newGame.CoverPhoto,
|
||||
Description = newGame.Description
|
||||
}
|
||||
});
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
foreach (var release in newGame.Releases)
|
||||
{
|
||||
if (!Database.Consoles.TryGet(release.ConsoleId, out var console)) continue;
|
||||
|
||||
game.Entity.Releases.Add(new Release()
|
||||
{
|
||||
ReleaseDate = release.Release,
|
||||
Console = console
|
||||
});
|
||||
}
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
return Ok(game);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Game CRUD
|
||||
|
||||
#region Releases CUD
|
||||
|
||||
[HttpPatch("{gameId:guid}/releases")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> PatchReleaseAsync([FromQuery] Guid gameId, [FromBody] PostRelease release)
|
||||
{
|
||||
if (!Database.Games.TryGet(gameId, out Game game)) return NotFound();
|
||||
if (!Database.Consoles.TryGet(release.ConsoleId, out var console)) return NotFound();
|
||||
|
||||
try
|
||||
{
|
||||
game.Releases.Add(Release.New(release.Release, console));
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut("{gameId:guid}/releases/{releaseId:guid}")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> PatchReleaseAsync([FromQuery] Guid gameId, [FromQuery] Guid releaseId, [FromBody] DateTime newReleaseDate)
|
||||
{
|
||||
if (!Database.Games.TryGet(gameId, out Game game)) return NotFound();
|
||||
if (!game.Releases.TryGet(releaseId, out var release)) return NotFound();
|
||||
|
||||
try
|
||||
{
|
||||
release.ReleaseDate = newReleaseDate;
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("{gameId:guid}/releases/{releaseId:guid}")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> DeleteReleaseAsync([FromQuery] Guid gameId, [FromQuery] Guid releaseId)
|
||||
{
|
||||
if (!Database.Games.TryGet(gameId, out Game game)) return NotFound();
|
||||
if (!game.Releases.TryGet(releaseId, out Release release)) return NotFound();
|
||||
|
||||
try
|
||||
{
|
||||
game.Releases.Remove(release);
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Releases CUD
|
||||
}
|
||||
20
DreamsCaster/Dockerfile
Normal file
20
DreamsCaster/Dockerfile
Normal file
@@ -0,0 +1,20 @@
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["DreamsCaster/DreamsCaster.csproj", "DreamsCaster/"]
|
||||
RUN dotnet restore "DreamsCaster/DreamsCaster.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/DreamsCaster"
|
||||
RUN dotnet build "DreamsCaster.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "DreamsCaster.csproj" -c Release -o /app/publish
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "DreamsCaster.dll"]
|
||||
17
DreamsCaster/DreamsCaster.csproj
Normal file
17
DreamsCaster/DreamsCaster.csproj
Normal file
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.10" />
|
||||
<PackageReference Include="PagedList.EntityFramework" Version="1.0.1" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.2" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
15
DreamsCaster/Helpers/Optional.cs
Normal file
15
DreamsCaster/Helpers/Optional.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace DreamsCaster.Helpers;
|
||||
|
||||
public struct Optional<T>
|
||||
{
|
||||
public bool HasValue;
|
||||
public T Value;
|
||||
|
||||
public Optional(bool hasValue, T value)
|
||||
{
|
||||
HasValue = hasValue;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public static implicit operator T(Optional<T> d) => d.HasValue ? d.Value : default;
|
||||
}
|
||||
17
DreamsCaster/Models/Common.cs
Normal file
17
DreamsCaster/Models/Common.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace DreamsCaster.Models;
|
||||
|
||||
public class IdEntity
|
||||
{
|
||||
public Guid Id;
|
||||
}
|
||||
|
||||
public class MetaData<T> : IdEntity
|
||||
{
|
||||
public string Description;
|
||||
public string CoverPhoto;
|
||||
|
||||
[Required]
|
||||
public virtual T Owner { get; set; }
|
||||
}
|
||||
10
DreamsCaster/Models/Console.cs
Normal file
10
DreamsCaster/Models/Console.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace DreamsCaster.Models;
|
||||
|
||||
public class Console : IdEntity
|
||||
{
|
||||
public string Name;
|
||||
|
||||
public virtual ICollection<Game> Games { get; set; }
|
||||
|
||||
public virtual MetaData<Console> Data { get; set; }
|
||||
}
|
||||
10
DreamsCaster/Models/Game.cs
Normal file
10
DreamsCaster/Models/Game.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace DreamsCaster.Models;
|
||||
|
||||
public class Game : IdEntity
|
||||
{
|
||||
public string Name;
|
||||
|
||||
public ICollection<Release> Releases;
|
||||
|
||||
public virtual MetaData<Game> Data { get; set; }
|
||||
}
|
||||
19
DreamsCaster/Models/Release.cs
Normal file
19
DreamsCaster/Models/Release.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace DreamsCaster.Models;
|
||||
|
||||
public class Release : IdEntity
|
||||
{
|
||||
public DateTime ReleaseDate;
|
||||
|
||||
[Required]
|
||||
public virtual Game Game { get; set; }
|
||||
[Required]
|
||||
public virtual Console Console { get; set; }
|
||||
|
||||
public static Release New(DateTime date, Console console)
|
||||
=> new()
|
||||
{
|
||||
ReleaseDate = date, Console = console
|
||||
};
|
||||
}
|
||||
25
DreamsCaster/Program.cs
Normal file
25
DreamsCaster/Program.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
|
||||
builder.Services.AddControllers();
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
31
DreamsCaster/Properties/launchSettings.json
Normal file
31
DreamsCaster/Properties/launchSettings.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:1386",
|
||||
"sslPort": 44381
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"DreamsCaster": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:7058;http://localhost:5273",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
DreamsCaster/appsettings.Development.json
Normal file
8
DreamsCaster/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
DreamsCaster/appsettings.json
Normal file
9
DreamsCaster/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
Reference in New Issue
Block a user