feat: add album and miscellaneous controllers with album mapping
All checks were successful
Update changelog / changelog (push) Successful in 26s
All checks were successful
Update changelog / changelog (push) Successful in 26s
This commit is contained in:
135
Controllers/AlbumController.cs
Normal file
135
Controllers/AlbumController.cs
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
using Shadow.Data;
|
||||||
|
using Shadow.DTOs;
|
||||||
|
using Shadow.Entities;
|
||||||
|
using Shadow.Mapping;
|
||||||
|
using Shadow.Tools;
|
||||||
|
|
||||||
|
namespace Shadow.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("rest")]
|
||||||
|
[Produces("application/json")]
|
||||||
|
public class AlbumController : ControllerBase
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly ApplicationDbContext db;
|
||||||
|
private readonly GeneralUseHelpers guhf;
|
||||||
|
|
||||||
|
public AlbumController(ApplicationDbContext _db, GeneralUseHelpers _guhf)
|
||||||
|
{
|
||||||
|
db = _db;
|
||||||
|
guhf = _guhf;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("getCoverArt")]
|
||||||
|
[HttpGet("getCoverArt.view")]
|
||||||
|
[HttpPost("getCoverArt.view")]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
[ProducesResponseType(404)]
|
||||||
|
public async Task<IActionResult> GetCoverArt()
|
||||||
|
{
|
||||||
|
string thumbnailPath = db.Globals
|
||||||
|
.First(g => g.Key == "musicThumbnailPath").Value!;
|
||||||
|
|
||||||
|
IFileInfo fileInfo = new PhysicalFileProvider(thumbnailPath)
|
||||||
|
.GetFileInfo("default.png");
|
||||||
|
|
||||||
|
if (!fileInfo.Exists) return NotFound();
|
||||||
|
return PhysicalFile(fileInfo.PhysicalPath!, "image/png");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("getAlbumList2")]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
public async Task<IActionResult> GetAlbumList2()
|
||||||
|
{
|
||||||
|
// First, check if user is authorized
|
||||||
|
User? user = await guhf.GetUserFromParams(Request);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
// Craft an error
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO
|
||||||
|
{
|
||||||
|
Status = "failed",
|
||||||
|
error = new ErrorDTO()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AlbumViewShortDTO> albumsDTO = [];
|
||||||
|
List<Album> albums = db.Albums
|
||||||
|
.Where(a => a.State != 1)
|
||||||
|
.Include(a => a.Artist)
|
||||||
|
.Include(a => a.Songs)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (Album al in albums)
|
||||||
|
{
|
||||||
|
albumsDTO.Add(
|
||||||
|
AlbumMapping.ToAlbumViewShort(al)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO
|
||||||
|
{
|
||||||
|
albumList2 = new AlbumList2DTO
|
||||||
|
{
|
||||||
|
album = albumsDTO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("getAlbumList2.view")]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
public async Task<IActionResult> GetAlbumList2Form()
|
||||||
|
{
|
||||||
|
// First, check if user is authorized
|
||||||
|
User? user = await guhf.GetUserFromForm(Request);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
// Craft an error
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO
|
||||||
|
{
|
||||||
|
Status = "failed",
|
||||||
|
error = new ErrorDTO()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AlbumViewShortDTO> albumsDTO = [];
|
||||||
|
List<Album> albums = db.Albums
|
||||||
|
.Where(a => a.State != 1)
|
||||||
|
.Include(a => a.Artist)
|
||||||
|
.Include(a => a.Songs)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (Album al in albums)
|
||||||
|
{
|
||||||
|
albumsDTO.Add(
|
||||||
|
AlbumMapping.ToAlbumViewShort(al)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO
|
||||||
|
{
|
||||||
|
albumList2 = new AlbumList2DTO
|
||||||
|
{
|
||||||
|
album = albumsDTO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
153
Controllers/MiscController.cs
Normal file
153
Controllers/MiscController.cs
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Shadow.Data;
|
||||||
|
using Shadow.DTOs;
|
||||||
|
using Shadow.Entities;
|
||||||
|
using Shadow.Tools;
|
||||||
|
|
||||||
|
namespace Shadow.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("rest")]
|
||||||
|
[Produces("application/json")]
|
||||||
|
public class MiscController : ControllerBase
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly ApplicationDbContext db;
|
||||||
|
private readonly GeneralUseHelpers guhf;
|
||||||
|
|
||||||
|
public MiscController(ApplicationDbContext _db, GeneralUseHelpers _guhf)
|
||||||
|
{
|
||||||
|
db = _db;
|
||||||
|
guhf = _guhf;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("ping")]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
public async Task<IActionResult> Ping()
|
||||||
|
{
|
||||||
|
User? user = await guhf.GetUserFromParams(Request);
|
||||||
|
|
||||||
|
// Wrong credentials?
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
// Craft an error
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO
|
||||||
|
{
|
||||||
|
Status = "failed",
|
||||||
|
error = new ErrorDTO
|
||||||
|
{
|
||||||
|
code = 40,
|
||||||
|
message = "Wrong username or password."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(new ResponseWrapper {
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("ping.view")]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
public async Task<IActionResult> PingForm()
|
||||||
|
{
|
||||||
|
User? user = await guhf.GetUserFromForm(Request);
|
||||||
|
|
||||||
|
// Wrong credentials?
|
||||||
|
if (user == null) {
|
||||||
|
// Craft an error
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO {
|
||||||
|
Status = "failed",
|
||||||
|
error = new ErrorDTO {
|
||||||
|
code = 40,
|
||||||
|
message = "Wrong username or password."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("getUser")]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
public async Task<IActionResult> GetUser()
|
||||||
|
{
|
||||||
|
User? user = await guhf.GetUserFromParams(Request);
|
||||||
|
|
||||||
|
// Wrong credentials?
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
// Craft an error
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO
|
||||||
|
{
|
||||||
|
Status = "failed",
|
||||||
|
error = new ErrorDTO
|
||||||
|
{
|
||||||
|
code = 40,
|
||||||
|
message = "Wrong username or password."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO
|
||||||
|
{
|
||||||
|
userPing = new UserPingDTO
|
||||||
|
{
|
||||||
|
username = user.Name,
|
||||||
|
adminRole = user.IsAdmin()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("getUser.view")]
|
||||||
|
[ProducesResponseType(200)]
|
||||||
|
public async Task<IActionResult> GetUserForm()
|
||||||
|
{
|
||||||
|
User? user = await guhf.GetUserFromForm(Request);
|
||||||
|
|
||||||
|
// Wrong credentials?
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
// Craft an error
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO
|
||||||
|
{
|
||||||
|
Status = "failed",
|
||||||
|
error = new ErrorDTO
|
||||||
|
{
|
||||||
|
code = 40,
|
||||||
|
message = "Wrong username or password."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(new ResponseWrapper
|
||||||
|
{
|
||||||
|
SubsonicResponse = new SubsonicResponseDTO
|
||||||
|
{
|
||||||
|
userPing = new UserPingDTO
|
||||||
|
{
|
||||||
|
username = user.Name,
|
||||||
|
adminRole = user.IsAdmin()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
27
Mapping/AlbumMapping.cs
Normal file
27
Mapping/AlbumMapping.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using Shadow.DTOs;
|
||||||
|
using Shadow.Entities;
|
||||||
|
|
||||||
|
namespace Shadow.Mapping;
|
||||||
|
|
||||||
|
public static class AlbumMapping
|
||||||
|
{
|
||||||
|
public static AlbumViewShortDTO ToAlbumViewShort(Album album)
|
||||||
|
{
|
||||||
|
AlbumViewShortDTO dto = new AlbumViewShortDTO
|
||||||
|
{
|
||||||
|
id = $"{album.Id}",
|
||||||
|
name = album.Name,
|
||||||
|
artist = album.Artist?.Name ?? "[Unknown Artist]",
|
||||||
|
artistId = $"{album.ArtistId}",
|
||||||
|
coverArt = "default.png",
|
||||||
|
songCount = album.Songs.Count,
|
||||||
|
duration = album.Songs.Sum(s => s.Duration),
|
||||||
|
playCount = 0,
|
||||||
|
year = 0,
|
||||||
|
genre = "unknown",
|
||||||
|
// played = "never"
|
||||||
|
};
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using Shadow.Data;
|
using Shadow.Data;
|
||||||
using Shadow.Entities;
|
using Shadow.Entities;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace Shadow.Tools;
|
namespace Shadow.Tools;
|
||||||
|
|
||||||
@@ -46,4 +47,55 @@ public class GeneralUseHelpers(ApplicationDbContext? db = null, IConfiguration?
|
|||||||
|
|
||||||
return "{" + resultJson[..^2] + "}";
|
return "{" + resultJson[..^2] + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<User?> GetUserFromForm(HttpRequest request)
|
||||||
|
{
|
||||||
|
User? user = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string username = request.Form["u"]!;
|
||||||
|
string saltedPassword = request.Form["t"]!;
|
||||||
|
string sesame = request.Form["s"]!;
|
||||||
|
|
||||||
|
User? foundUser = _db?.Users
|
||||||
|
.FirstOrDefault(u => u.NormalizedName == username.ToLower());
|
||||||
|
|
||||||
|
if (foundUser == null)
|
||||||
|
return user;
|
||||||
|
|
||||||
|
string resaltedPassword = MetadataExtractor.GetStringMD5($"{foundUser.Password}{sesame}");
|
||||||
|
if (resaltedPassword == saltedPassword)
|
||||||
|
user = foundUser;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
user = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<User?> GetUserFromParams(HttpRequest request)
|
||||||
|
{
|
||||||
|
User? user = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string username = request.Query["u"]!;
|
||||||
|
string saltedPassword = request.Query["t"]!;
|
||||||
|
string sesame = request.Query["s"]!;
|
||||||
|
|
||||||
|
User foundUser = _db!.Users
|
||||||
|
.FirstOrDefault(u => u.NormalizedName == username.ToLower())!;
|
||||||
|
|
||||||
|
string resaltedPassword = MetadataExtractor.GetStringMD5($"{foundUser.Password}{sesame}");
|
||||||
|
if (resaltedPassword == saltedPassword)
|
||||||
|
user = foundUser;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
user = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user