Добавлены права на воспроизведение.
This commit is contained in:
@@ -13,15 +13,18 @@ public class AudioController : ControllerBase
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly YandexMusicService _yandexService;
|
||||
private readonly SharedPlaylistService _sharedService;
|
||||
private readonly JwtService _jwtService;
|
||||
|
||||
public AudioController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
YandexMusicService yandexService,
|
||||
SharedPlaylistService sharedService,
|
||||
JwtService jwtService)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_yandexService = yandexService;
|
||||
_sharedService = sharedService;
|
||||
_jwtService = jwtService;
|
||||
}
|
||||
|
||||
@@ -29,17 +32,18 @@ public class AudioController : ControllerBase
|
||||
/// Потоковое воспроизведение трека из Яндекс.Музыки.
|
||||
/// </summary>
|
||||
/// <param name="trackId">ID трека (например, "21696942").</param>
|
||||
/// <param name="access_token">gwt пользователя</param>
|
||||
/// <param name="shared_id">ID расшаренного плейлиста</param>
|
||||
[HttpGet("track/{trackId}")]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> StreamTrack(string trackId, [FromQuery] string? access_token = null)
|
||||
public async Task<IActionResult> StreamTrack(string trackId, [FromQuery] string? access_token = null, [FromQuery] string? shared_id = null)
|
||||
{
|
||||
var user = await GetUserFromToken(access_token);
|
||||
if (user == null)
|
||||
return Unauthorized();
|
||||
if (user == null) user = await GetUserFromSharedPlaylistId(shared_id);
|
||||
if (user == null) return Unauthorized();
|
||||
|
||||
var streamUrl = await _yandexService.GetTrackFileUrlAsync(user, trackId);
|
||||
if (string.IsNullOrEmpty(streamUrl))
|
||||
return NotFound();
|
||||
if (string.IsNullOrEmpty(streamUrl)) return NotFound();
|
||||
|
||||
var httpClient = new HttpClient();
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, streamUrl);
|
||||
@@ -56,11 +60,11 @@ public class AudioController : ControllerBase
|
||||
Response.ContentType = response.Content.Headers.ContentType?.ToString() ?? "audio/mpeg";
|
||||
|
||||
if (response.Content.Headers.Contains("Content-Range"))
|
||||
Response.Headers.Add("Content-Range", response.Content.Headers.ContentRange?.ToString());
|
||||
Response.Headers.Append("Content-Range", response.Content.Headers.ContentRange?.ToString());
|
||||
if (response.Headers.Contains("Accept-Ranges"))
|
||||
Response.Headers.Add("Accept-Ranges", response.Headers.AcceptRanges?.ToString());
|
||||
Response.Headers.Append("Accept-Ranges", response.Headers.AcceptRanges?.ToString());
|
||||
if (response.Content.Headers.Contains("Content-Length"))
|
||||
Response.Headers.Add("Content-Length", response.Content.Headers.ContentLength?.ToString());
|
||||
Response.Headers.Append("Content-Length", response.Content.Headers.ContentLength?.ToString());
|
||||
|
||||
await response.Content.CopyToAsync(Response.Body);
|
||||
return new EmptyResult();
|
||||
@@ -68,17 +72,28 @@ public class AudioController : ControllerBase
|
||||
|
||||
private async Task<ApplicationUser?> GetUserFromToken(string? token)
|
||||
{
|
||||
if (string.IsNullOrEmpty(token))
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(token)) return null;
|
||||
|
||||
var principal = _jwtService.ValidateToken(token);
|
||||
if (principal == null)
|
||||
return null;
|
||||
if (principal == null) return null;
|
||||
|
||||
var userId = principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
||||
if (string.IsNullOrEmpty(userId))
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(userId)) return null;
|
||||
|
||||
return await _userManager.FindByIdAsync(userId);
|
||||
}
|
||||
|
||||
private async Task<ApplicationUser?> GetUserFromSharedPlaylistId(string? sharedId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sharedId)) return null;
|
||||
|
||||
var playlist = await _sharedService.GetEntityByTokenAsync(sharedId);
|
||||
|
||||
if (playlist == null) return null;
|
||||
|
||||
if (!await _sharedService.CanPlayEveryoneAsync(playlist)) return null;
|
||||
|
||||
return await _userManager.FindByIdAsync(playlist.CreatorUserId.ToString());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -87,8 +87,9 @@ public class PlaylistsController : ControllerBase
|
||||
Title = playlist.Title,
|
||||
Description = playlist.Description,
|
||||
ViewPermission = ViewPermission.Everyone,
|
||||
PlayPermission = ViewPermission.Everyone,
|
||||
AddPermission = EditPermission.AuthorizedOnly,
|
||||
RemovePermission = EditPermission.AddedByUserOnly
|
||||
RemovePermission = EditPermission.AddedByUserOnly,
|
||||
};
|
||||
|
||||
var result = await _sharedService.CreateAsync(userId, dto);
|
||||
|
||||
547
PlaylistShared.Api/Data/Migrations/20260414094124_AddSharedPermissions.Designer.cs
generated
Normal file
547
PlaylistShared.Api/Data/Migrations/20260414094124_AddSharedPermissions.Designer.cs
generated
Normal file
@@ -0,0 +1,547 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using PlaylistShared.Api.Data;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace PlaylistShared.Api.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20260414094124_AddSharedPermissions")]
|
||||
partial class AddSharedPermissions
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.5")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole<System.Guid>", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex")
|
||||
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<Guid>("RoleId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<Guid>("RoleId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlaylistShared.Api.Entities.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetimeoffset");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("RefreshToken")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTime>("RefreshTokenExpiryUtc")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("YandexAccessToken")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("YandexId")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("YandexRefreshToken")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTime>("YandexTokenExpiryUtc")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex")
|
||||
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlaylistShared.Api.Entities.SharedPlaylist", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int>("AddPermission")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CoverUrl")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid>("CreatorUserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<int>("PlayPermission")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("RemovePermission")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ShareToken")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("nvarchar(255)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<int>("ViewPermission")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("YandexPlaylistKind")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.Property<string>("YandexPlaylistOwnerUid")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatorUserId");
|
||||
|
||||
b.HasIndex("ShareToken")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("SharedPlaylists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlaylistShared.Api.Entities.TrackAdditionLog", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime>("AddedAtUtc")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("AddedByUserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("SessionId")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(449)");
|
||||
|
||||
b.Property<Guid>("SharedPlaylistId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("TrackId")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AddedByUserId");
|
||||
|
||||
b.HasIndex("SessionId");
|
||||
|
||||
b.HasIndex("SharedPlaylistId", "TrackId");
|
||||
|
||||
b.ToTable("TrackAdditionLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlaylistShared.Api.Entities.UserSession", b =>
|
||||
{
|
||||
b.Property<string>("SessionId")
|
||||
.HasMaxLength(449)
|
||||
.HasColumnType("nvarchar(449)");
|
||||
|
||||
b.Property<Guid?>("AssociatedUserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("ClientIpAddress")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTime>("FirstSeenUtc")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<DateTime>("LastSeenUtc")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("UserAgent")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("SessionId");
|
||||
|
||||
b.HasIndex("AssociatedUserId");
|
||||
|
||||
b.ToTable("UserSessions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TrackRemovalLog", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime>("RemovedAtUtc")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("RemovedByUserId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("SessionId")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(449)");
|
||||
|
||||
b.Property<Guid>("SharedPlaylistId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("TrackId")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RemovedByUserId");
|
||||
|
||||
b.HasIndex("SessionId");
|
||||
|
||||
b.HasIndex("SharedPlaylistId", "TrackId");
|
||||
|
||||
b.ToTable("TrackRemovalLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole<System.Guid>", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("PlaylistShared.Api.Entities.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("PlaylistShared.Api.Entities.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole<System.Guid>", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PlaylistShared.Api.Entities.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("PlaylistShared.Api.Entities.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlaylistShared.Api.Entities.SharedPlaylist", b =>
|
||||
{
|
||||
b.HasOne("PlaylistShared.Api.Entities.ApplicationUser", "Creator")
|
||||
.WithMany("OwnedPlaylists")
|
||||
.HasForeignKey("CreatorUserId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Creator");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlaylistShared.Api.Entities.TrackAdditionLog", b =>
|
||||
{
|
||||
b.HasOne("PlaylistShared.Api.Entities.ApplicationUser", "AddedByUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("AddedByUserId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("PlaylistShared.Api.Entities.UserSession", "Session")
|
||||
.WithMany("TrackAdditionLogs")
|
||||
.HasForeignKey("SessionId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PlaylistShared.Api.Entities.SharedPlaylist", "SharedPlaylist")
|
||||
.WithMany("TrackAdditionLogs")
|
||||
.HasForeignKey("SharedPlaylistId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AddedByUser");
|
||||
|
||||
b.Navigation("Session");
|
||||
|
||||
b.Navigation("SharedPlaylist");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlaylistShared.Api.Entities.UserSession", b =>
|
||||
{
|
||||
b.HasOne("PlaylistShared.Api.Entities.ApplicationUser", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("AssociatedUserId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("TrackRemovalLog", b =>
|
||||
{
|
||||
b.HasOne("PlaylistShared.Api.Entities.ApplicationUser", "RemovedByUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("RemovedByUserId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("PlaylistShared.Api.Entities.UserSession", "Session")
|
||||
.WithMany("TrackRemovalLogs")
|
||||
.HasForeignKey("SessionId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("PlaylistShared.Api.Entities.SharedPlaylist", "SharedPlaylist")
|
||||
.WithMany()
|
||||
.HasForeignKey("SharedPlaylistId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("RemovedByUser");
|
||||
|
||||
b.Navigation("Session");
|
||||
|
||||
b.Navigation("SharedPlaylist");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlaylistShared.Api.Entities.ApplicationUser", b =>
|
||||
{
|
||||
b.Navigation("OwnedPlaylists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlaylistShared.Api.Entities.SharedPlaylist", b =>
|
||||
{
|
||||
b.Navigation("TrackAdditionLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PlaylistShared.Api.Entities.UserSession", b =>
|
||||
{
|
||||
b.Navigation("TrackAdditionLogs");
|
||||
|
||||
b.Navigation("TrackRemovalLogs");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace PlaylistShared.Api.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddSharedPermissions : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "PlayPermission",
|
||||
table: "SharedPlaylists",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PlayPermission",
|
||||
table: "SharedPlaylists");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,6 +261,9 @@ namespace PlaylistShared.Api.Data.Migrations
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<int>("PlayPermission")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("RemovePermission")
|
||||
.HasColumnType("int");
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ public class SharedPlaylist
|
||||
public bool IsDeleted { get; set; }
|
||||
public string ShareToken { get; set; } = null!;
|
||||
public ViewPermission ViewPermission { get; set; }
|
||||
public ViewPermission PlayPermission { get; set; }
|
||||
public EditPermission AddPermission { get; set; }
|
||||
public EditPermission RemovePermission { get; set; }
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ public class Program
|
||||
|
||||
// DbContext
|
||||
builder.Services.AddDbContext<ApplicationDbContext>(options =>
|
||||
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));// Identity
|
||||
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
|
||||
// Identity
|
||||
builder.Services.AddIdentity<ApplicationUser, IdentityRole<Guid>>(options =>
|
||||
{
|
||||
options.User.RequireUniqueEmail = true;
|
||||
@@ -101,17 +102,9 @@ public class Program
|
||||
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("Development", policy =>
|
||||
{
|
||||
policy.WithOrigins("http://localhost:5053", "https://localhost:7225", "http://localhost:5181", "https://api.playlistshare.frigat.duckdns.org", "https://playlistshare.frigat.duckdns.org")
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials();
|
||||
});
|
||||
|
||||
options.AddPolicy("Production", policy =>
|
||||
{
|
||||
policy.WithOrigins("https://api.playlistshare.frigat.duckdns.org", "https://playlistshare.frigat.duckdns.org")
|
||||
policy.WithOrigins(builder.Configuration.GetSection("Cors:Origins").Get<string[]>())
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials();
|
||||
@@ -131,17 +124,14 @@ public class Program
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseCors("Development");
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseCors("Production");
|
||||
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseHttpsRedirection();
|
||||
app.UseCors("Production");
|
||||
}
|
||||
|
||||
|
||||
app.UseSession();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
@@ -34,6 +34,7 @@ public class SharedPlaylistService
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
UpdatedAt = DateTime.UtcNow,
|
||||
ShareToken = GenerateToken(),
|
||||
PlayPermission = dto.PlayPermission,
|
||||
ViewPermission = dto.ViewPermission,
|
||||
AddPermission = dto.AddPermission,
|
||||
RemovePermission = dto.RemovePermission
|
||||
@@ -63,6 +64,7 @@ public class SharedPlaylistService
|
||||
var entity = await _db.SharedPlaylists.FindAsync(playlistId);
|
||||
if (entity == null) return null;
|
||||
entity.ViewPermission = dto.ViewPermission;
|
||||
entity.PlayPermission = dto.PlayPermission;
|
||||
entity.AddPermission = dto.AddPermission;
|
||||
entity.RemovePermission = dto.RemovePermission;
|
||||
entity.UpdatedAt = DateTime.UtcNow;
|
||||
@@ -80,6 +82,18 @@ public class SharedPlaylistService
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> CanPlayAsync(SharedPlaylist playlist, Guid? currentUserId)
|
||||
{
|
||||
if (currentUserId == playlist.CreatorUserId) return true;
|
||||
return playlist.PlayPermission == ViewPermission.Everyone ||
|
||||
(playlist.PlayPermission == ViewPermission.AuthorizedOnly && currentUserId.HasValue);
|
||||
}
|
||||
|
||||
public async Task<bool> CanPlayEveryoneAsync(SharedPlaylist playlist)
|
||||
{
|
||||
return playlist.PlayPermission == ViewPermission.Everyone;
|
||||
}
|
||||
|
||||
public async Task<bool> CanViewAsync(SharedPlaylist playlist, Guid? currentUserId)
|
||||
{
|
||||
if (currentUserId == playlist.CreatorUserId) return true;
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
"Issuer": "PlaylistShared.Api",
|
||||
"Audience": "PlaylistShared.Client"
|
||||
},
|
||||
"Cors": {
|
||||
"Origins": [
|
||||
"https://api.playlistshare.frigat.duckdns.org",
|
||||
"https://playlistshare.frigat.duckdns.org"
|
||||
]
|
||||
},
|
||||
"Yandex": {
|
||||
"ClientId": "0916685f8a3641ca8fc382dbccf77236",
|
||||
"ClientSecret": "f7398893cd814f8b84b85aeb2a0a6698"
|
||||
|
||||
Reference in New Issue
Block a user