diff --git a/Roadie.Api.Library/Models/TrackList.cs b/Roadie.Api.Library/Models/TrackList.cs
index 64bc8ab..cfe225a 100644
--- a/Roadie.Api.Library/Models/TrackList.cs
+++ b/Roadie.Api.Library/Models/TrackList.cs
@@ -77,7 +77,8 @@ namespace Roadie.Library.Models
public int? FileSize { get; set; }
- public static TrackList FromDataTrack(Data.Track track,
+ public static TrackList FromDataTrack(string trackPlayUrl,
+ Data.Track track,
int releaseMediaNumber,
Data.Release release,
Data.Artist artist,
@@ -111,7 +112,7 @@ namespace Roadie.Library.Models
PlayedCount = track.PlayedCount,
Rating = track.Rating,
Title = track.Title,
- TrackPlayUrl = $"{ baseUrl }/play/track/{ track.RoadieId }.mp3",
+ TrackPlayUrl = trackPlayUrl,
Thumbnail = trackThumbnail
};
diff --git a/Roadie.Api.Library/Roadie.Api.Library.csproj b/Roadie.Api.Library/Roadie.Api.Library.csproj
index 1bf5487..d25a28f 100644
--- a/Roadie.Api.Library/Roadie.Api.Library.csproj
+++ b/Roadie.Api.Library/Roadie.Api.Library.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/Roadie.Api.Services/BookmarkService.cs b/Roadie.Api.Services/BookmarkService.cs
index 578c63e..36f000a 100644
--- a/Roadie.Api.Services/BookmarkService.cs
+++ b/Roadie.Api.Services/BookmarkService.cs
@@ -61,6 +61,8 @@ namespace Roadie.Api.Services
var rowCount = result.Count();
BookmarkList[] rows = result.OrderBy(sortBy).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
+ var user = this.GetUser(roadieUser.UserId);
+
foreach (var row in rows)
{
switch (row.Type)
@@ -101,7 +103,8 @@ namespace Roadie.Api.Services
Text = track.Title,
Value = track.RoadieId.ToString()
};
- row.Track = TrackList.FromDataTrack(track,
+ row.Track = TrackList.FromDataTrack(this.MakeTrackPlayUrl(user, track.Id, track.RoadieId),
+ track,
track.ReleaseMedia.MediaNumber,
track.ReleaseMedia.Release,
track.ReleaseMedia.Release.Artist,
@@ -111,6 +114,7 @@ namespace Roadie.Api.Services
this.MakeReleaseThumbnailImage(track.ReleaseMedia.Release.RoadieId),
this.MakeArtistThumbnailImage(track.ReleaseMedia.Release.Artist.RoadieId),
this.MakeArtistThumbnailImage(track.TrackArtist == null ? null : (Guid?)track.TrackArtist.RoadieId));
+ row.Track.TrackPlayUrl = this.MakeTrackPlayUrl(user, track.Id, track.RoadieId);
row.Thumbnail = this.MakeTrackThumbnailImage(track.RoadieId);
row.SortName = track.Title;
break;
diff --git a/Roadie.Api.Services/PlaylistService.cs b/Roadie.Api.Services/PlaylistService.cs
index d3d544b..eaad1d9 100644
--- a/Roadie.Api.Services/PlaylistService.cs
+++ b/Roadie.Api.Services/PlaylistService.cs
@@ -147,6 +147,15 @@ namespace Roadie.Api.Services
sw.Stop();
if (result?.Data != null && roadieUser != null)
{
+ if (result?.Data?.Tracks != null)
+ {
+ var user = this.GetUser(roadieUser.UserId);
+ foreach (var track in result.Data.Tracks)
+ {
+ track.Track.TrackPlayUrl = this.MakeTrackPlayUrl(user, track.Track.DatabaseId, track.Track.Id);
+ }
+ }
+
result.Data.UserCanEdit = result.Data.Maintainer.Id == roadieUser.UserId || roadieUser.IsAdmin;
var userBookmarkResult = await this.BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Playlist);
if (userBookmarkResult.IsSuccess)
@@ -294,7 +303,8 @@ namespace Roadie.Api.Services
select new PlaylistTrack
{
ListNumber = plt.pltr.ListNumber,
- Track = TrackList.FromDataTrack(plt.t,
+ Track = TrackList.FromDataTrack(null,
+ plt.t,
rm.MediaNumber,
r,
releaseArtist,
diff --git a/Roadie.Api.Services/ReleaseService.cs b/Roadie.Api.Services/ReleaseService.cs
index 3a14af8..6392fd1 100644
--- a/Roadie.Api.Services/ReleaseService.cs
+++ b/Roadie.Api.Services/ReleaseService.cs
@@ -101,6 +101,15 @@ namespace Roadie.Api.Services
}
if (result.Data.Medias != null)
{
+ var user = this.GetUser(roadieUser.UserId);
+ foreach(var media in result.Data.Medias)
+ {
+ foreach(var track in media.Tracks)
+ {
+ track.TrackPlayUrl = this.MakeTrackPlayUrl(user, track.DatabaseId, track.Id);
+ }
+ }
+
var releaseTrackIds = result.Data.Medias.SelectMany(x => x.Tracks).Select(x => x.Id);
var releaseUserTracks = (from ut in this.DbContext.UserTracks
join t in this.DbContext.Tracks on ut.TrackId equals t.Id
@@ -421,6 +430,7 @@ namespace Roadie.Api.Services
where ut.UserId == roadieUser.Id
where (from x in releaseTrackIds select x).Contains(ut.TrackId)
select ut).ToArray();
+ var user = this.GetUser(roadieUser.UserId);
foreach (var release in rows)
{
var releaseMedias = new List();
@@ -432,7 +442,7 @@ namespace Roadie.Api.Services
{
var t = track.t.Adapt();
t.CssClass = string.IsNullOrEmpty(track.t.Hash) ? "Missing" : "Ok";
- t.TrackPlayUrl = $"{ this.HttpContext.BaseUrl }/play/track/{ track.t.RoadieId}.mp3";
+ t.TrackPlayUrl = this.MakeTrackPlayUrl(user, track.t.Id, track.t.RoadieId);
var userRating = artistUserTracks.FirstOrDefault(x => x.TrackId == track.t.Id);
if (userRating != null)
{
@@ -888,7 +898,6 @@ namespace Roadie.Api.Services
t.MediaNumber = rm.MediaNumber;
t.CssClass = string.IsNullOrEmpty(track.Hash) ? "Missing" : "Ok";
t.TrackArtist = track.TrackArtist != null ? ArtistList.FromDataArtist(track.TrackArtist, this.MakeArtistThumbnailImage(track.TrackArtist.RoadieId)) : null;
- t.TrackPlayUrl = $"{ this.HttpContext.BaseUrl }/play/track/{ t.Id}.mp3";
rmTracks.Add(t);
}
rm.Tracks = rmTracks;
diff --git a/Roadie.Api.Services/Roadie.Api.Services.csproj b/Roadie.Api.Services/Roadie.Api.Services.csproj
index 5d107c5..4613805 100644
--- a/Roadie.Api.Services/Roadie.Api.Services.csproj
+++ b/Roadie.Api.Services/Roadie.Api.Services.csproj
@@ -6,6 +6,7 @@
+
diff --git a/Roadie.Api.Services/ServiceBase.cs b/Roadie.Api.Services/ServiceBase.cs
index 6fb6f00..3ba1243 100644
--- a/Roadie.Api.Services/ServiceBase.cs
+++ b/Roadie.Api.Services/ServiceBase.cs
@@ -1,4 +1,5 @@
-using Microsoft.EntityFrameworkCore;
+using HashidsNet;
+using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Roadie.Library;
using Roadie.Library.Caching;
@@ -17,6 +18,8 @@ namespace Roadie.Api.Services
{
public abstract class ServiceBase
{
+ public static string TrackTokenSalt = "B0246908-FBD6-4E12-A96C-AF5B086115B3";
+
protected readonly ICacheManager _cacheManager = null;
protected readonly IRoadieSettings _configuration = null;
protected readonly data.IRoadieDbContext _dbContext = null;
@@ -699,5 +702,31 @@ namespace Roadie.Api.Services
this.CacheManager.ClearRegion(release.CacheRegion);
}
}
+
+ public static string TrackPlayToken(ApplicationUser user, Guid trackId)
+ {
+ var hashids = new Hashids(ServiceBase.TrackTokenSalt);
+ var trackIdPart = BitConverter.ToInt32(trackId.ToByteArray(), 6);
+ if(trackIdPart < 0)
+ {
+ trackIdPart = trackIdPart * -1;
+ }
+ var token = hashids.Encode(user.Id, SafeParser.ToNumber(user.CreatedDate.Value.ToString("DDHHmmss")), trackIdPart);
+ return token;
+ }
+
+ protected string MakeTrackPlayUrl(ApplicationUser user, int trackId, Guid trackRoadieId)
+ {
+ return $"{ this.HttpContext.BaseUrl }/play/track/{user.Id}/{ ServiceBase.TrackPlayToken(user, trackRoadieId)}/{ trackRoadieId }.mp3";
+ }
+
+ public static bool ConfirmTrackPlayToken(ApplicationUser user, Guid trackRoadieId, string token)
+ {
+ if(string.IsNullOrEmpty(token))
+ {
+ return false;
+ }
+ return ServiceBase.TrackPlayToken(user, trackRoadieId).Equals(token);
+ }
}
}
\ No newline at end of file
diff --git a/Roadie.Api.Services/TrackService.cs b/Roadie.Api.Services/TrackService.cs
index bff7660..b08ff5c 100644
--- a/Roadie.Api.Services/TrackService.cs
+++ b/Roadie.Api.Services/TrackService.cs
@@ -415,6 +415,7 @@ namespace Roadie.Api.Services
resultQuery = resultQuery.Where(x => x.ti.Tags != null && x.ti.Tags.Contains(tagValue));
}
}
+ var user = this.GetUser(roadieUser.UserId);
var result = resultQuery.Select(x =>
new TrackList
{
@@ -439,7 +440,7 @@ namespace Roadie.Api.Services
PlayedCount = x.ti.PlayedCount,
Rating = x.ti.Rating,
Title = x.ti.Title,
- TrackPlayUrl = $"{ this.HttpContext.BaseUrl }/play/track/{ x.ti.RoadieId }.mp3",
+ TrackPlayUrl = this.MakeTrackPlayUrl(user, x.ti.Id, x.ti.RoadieId),
Thumbnail = this.MakeTrackThumbnailImage(x.ti.RoadieId)
});
string sortBy = null;
diff --git a/Roadie.Api/Controllers/PlayController.cs b/Roadie.Api/Controllers/PlayController.cs
index a9e725c..6f5413f 100644
--- a/Roadie.Api/Controllers/PlayController.cs
+++ b/Roadie.Api/Controllers/PlayController.cs
@@ -65,10 +65,23 @@ namespace Roadie.Api.Controllers
return File(System.Text.Encoding.Default.GetBytes(m3u), "audio/mpeg-url");
}
- [HttpGet("track/{id}.{mp3?}")]
- public async Task StreamTrack(Guid id)
+ ///
+ /// This was done to use a URL based token as many clients don't support adding Auth Bearer tokens to audio requests.
+ ///
+ [HttpGet("track/{userId}/{trackPlayToken}/{id}.{mp3?}")]
+ [AllowAnonymous]
+ public async Task StreamTrack(int userId, string trackPlayToken, Guid id)
{
- return await base.StreamTrack(id, this.TrackService, this.PlayActivityService);
+ var user = this.UserManager.Users.FirstOrDefault(x => x.Id == userId);
+ if(user == null)
+ {
+ return StatusCode((int)HttpStatusCode.Forbidden);
+ }
+ if(!ServiceBase.ConfirmTrackPlayToken(user, id, trackPlayToken))
+ {
+ return StatusCode((int)HttpStatusCode.Forbidden);
+ }
+ return await base.StreamTrack(id, this.TrackService, this.PlayActivityService, this.UserModelForUser(user));
}
}
}
\ No newline at end of file
diff --git a/Roadie.Api/Roadie.Api.csproj b/Roadie.Api/Roadie.Api.csproj
index 1b1cea6..38bd2e4 100644
--- a/Roadie.Api/Roadie.Api.csproj
+++ b/Roadie.Api/Roadie.Api.csproj
@@ -29,7 +29,7 @@
-
+