Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix NewPlayList and polish #424

Merged
merged 1 commit into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions ClassTranscribeDatabase/Models/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,12 +245,12 @@ public class Playlist : Entity
public JObject JsonMetadata { get; set; } = new JObject(); // for serverside use
public string Options { get; set; } = "";

public virtual JObject getOptionsAsJson() {
public virtual JObject GetOptionsAsJson() {
return String.IsNullOrEmpty(this.Options) ? new JObject() : JObject.Parse(this.Options);
}

public virtual void setOptionsAsJson(JObject json) {
this.Options = json.ToString();
public virtual void SetOptionsAsJson(JObject json) {
this.Options = json.ToString(Newtonsoft.Json.Formatting.None);
}
public int Index { get; set; }
public Visibility Visibility { get; set; }
Expand Down Expand Up @@ -283,11 +283,11 @@ public class Media : Entity

public string Options { get; set; } = "";

public virtual JObject getOptionsAsJson() {
public virtual JObject GetOptionsAsJson() {
return String.IsNullOrEmpty(this.Options) ? new JObject() : JObject.Parse(this.Options);
}

public virtual void setOptionsAsJson(JObject json) {
public virtual void SetOptionsAsJson(JObject json) {
this.Options = json.ToString(Newtonsoft.Json.Formatting.None);
}
}
Expand Down
1 change: 1 addition & 0 deletions ClassTranscribeServer/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public class MediaWorkerLoginDTO
[HttpPost]
public async Task<ActionResult<LoggedInDTO>> MediaWorkerSignIn(MediaWorkerLoginDTO accessDTO)
{
if (accessDTO == null) return BadRequest("Missing parameter");
try
{
string access = accessDTO.Access;
Expand Down
8 changes: 4 additions & 4 deletions ClassTranscribeServer/Controllers/MediaController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public async Task<ActionResult<MediaDTO>> GetMedia(string id)
var playlist = await _context.Playlists.FindAsync(media.PlaylistId);
//unused var v = await _context.Videos.FindAsync(media.VideoId);
var user = await _userUtils.GetUser(User);
var restrict = (bool?) playlist.getOptionsAsJson()[ "restrictRoomStream"] ?? false;
var restrict = (bool?) playlist.GetOptionsAsJson()[ "restrictRoomStream"] ?? false;
var mediaDTO = new MediaDTO
{
Id = media.Id,
Expand All @@ -71,7 +71,7 @@ public async Task<ActionResult<MediaDTO>> GetMedia(string id)
SourceType = media.SourceType,
Duration = media.Video.Duration,
PublishStatus = media.PublishStatus,
Options = media.getOptionsAsJson(),
Options = media.GetOptionsAsJson(),
Transcriptions = media.Video.Transcriptions
.Select(t => new TranscriptionDTO
{
Expand Down Expand Up @@ -171,7 +171,7 @@ public async Task<IActionResult> PutMediaOption(string id, string option, string
if(value == null) return BadRequest("value not specified");

Media media = await _context.Medias.FindAsync(id);
JObject theOptions = media.getOptionsAsJson();
JObject theOptions = media.GetOptionsAsJson();
if (media == null)
{
return NotFound();
Expand All @@ -193,7 +193,7 @@ public async Task<IActionResult> PutMediaOption(string id, string option, string
} else {
return BadRequest("Invalid type");// should never happen
}
media.setOptionsAsJson(theOptions);
media.SetOptionsAsJson(theOptions);
await _context.SaveChangesAsync();
return NoContent();
}
Expand Down
67 changes: 46 additions & 21 deletions ClassTranscribeServer/Controllers/PlaylistsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public async Task<ActionResult<PlaylistDTO>> GetPlaylistsByVideoId(string videoI
PublishStatus = p.PublishStatus,
ListCheckedAt = p.ListCheckedAt,
ListUpdatedAt = p.ListUpdatedAt,
Options = p.getOptionsAsJson()
Options = p.GetOptionsAsJson()
}).ToList().FirstOrDefault();
return playlist;
}
Expand Down Expand Up @@ -109,7 +109,7 @@ public async Task<ActionResult<IEnumerable<PlaylistDTO>>> GetPlaylists(string of
PublishStatus = p.PublishStatus,
ListCheckedAt = p.ListCheckedAt,
ListUpdatedAt = p.ListUpdatedAt,
Options = p.getOptionsAsJson()
Options = p.GetOptionsAsJson()
}).ToList();
return playlists;
}
Expand Down Expand Up @@ -139,7 +139,7 @@ public async Task<ActionResult<IEnumerable<PlaylistDTO>>> GetPlaylists2(string o

var hideRoomVideos = new Dictionary<string,bool>();
foreach (var p in playLists) {
var restrict = (bool?) p.getOptionsAsJson()[ "restrictRoomStream"] ?? false;
var restrict = (bool?) p.GetOptionsAsJson()[ "restrictRoomStream"] ?? false;
hideRoomVideos.Add(p.Id, restrict);
};
var playlistDTOs = playLists.Select(p => new PlaylistDTO
Expand All @@ -154,7 +154,7 @@ public async Task<ActionResult<IEnumerable<PlaylistDTO>>> GetPlaylists2(string o
PublishStatus = p.PublishStatus,
ListCheckedAt = p.ListCheckedAt,
ListUpdatedAt = p.ListUpdatedAt,
Options = p.getOptionsAsJson(),
Options = p.GetOptionsAsJson(),
Medias = p.Medias.Where(m => m.Video != null).Select(m => new MediaDTO
{
Id = m.Id,
Expand All @@ -167,7 +167,7 @@ public async Task<ActionResult<IEnumerable<PlaylistDTO>>> GetPlaylists2(string o
SourceType = m.SourceType,
Duration = m.Video?.Duration,
PublishStatus = m.PublishStatus,
Options = m.getOptionsAsJson(),
Options = m.GetOptionsAsJson(),
Video = new VideoDTO
{
Id = m.Video.Id,
Expand Down Expand Up @@ -241,7 +241,7 @@ public async Task<ActionResult<PlaylistDTO>> GetPlaylist(string id)
// In memory transformation into DTO resut

var hideRoomVideos = new Dictionary<string,bool>();
var restrict = (bool?) p.getOptionsAsJson()[ "restrictRoomStream"] ?? false;
var restrict = (bool?) p.GetOptionsAsJson()[ "restrictRoomStream"] ?? false;

List<MediaDTO> mediasDTO = mediaList.Select(m => new MediaDTO
{
Expand All @@ -254,7 +254,7 @@ public async Task<ActionResult<PlaylistDTO>> GetPlaylist(string id)
SourceType = m.SourceType,
Duration = m.Video?.Duration,
PublishStatus = m.PublishStatus,
Options = m.getOptionsAsJson(),
Options = m.GetOptionsAsJson(),
SceneDetectReady = m.Video != null && m.Video.HasSceneObjectData(),
Ready = m.Video != null && "NoError" == m.Video.TranscriptionStatus ,
Video = m.Video == null ? null : new VideoDTO
Expand Down Expand Up @@ -288,7 +288,7 @@ public async Task<ActionResult<PlaylistDTO>> GetPlaylist(string id)
PublishStatus = p.PublishStatus,
ListUpdatedAt = p.ListUpdatedAt,
ListCheckedAt = p.ListCheckedAt,
Options = p.getOptionsAsJson()
Options = p.GetOptionsAsJson()
};
}

Expand All @@ -315,7 +315,7 @@ public async Task<IActionResult> PutPlaylistOptions(string id, JObject options)
return new ChallengeResult();
}

p.setOptionsAsJson(options);
p.SetOptionsAsJson(options);

try
{
Expand Down Expand Up @@ -364,7 +364,7 @@ public async Task<IActionResult> PutPlaylist(string id, PlaylistUpdateDTO playli
var p = await _context.Playlists.FindAsync(playlist.Id);

p.Name = playlist.Name;
p.setOptionsAsJson(playlist.Options);
p.SetOptionsAsJson(playlist.Options);
p.PublishStatus = playlist.PublishStatus;

try
Expand All @@ -390,18 +390,19 @@ public async Task<IActionResult> PutPlaylist(string id, PlaylistUpdateDTO playli
// POST: api/Playlists
[HttpPost]
[Authorize]
public async Task<ActionResult<Playlist>> PostPlaylist(Playlist playlist)
public async Task<ActionResult<PlaylistDTO>> PostPlaylist(NewPlaylistDTO playlist)
{

if (playlist == null || playlist.OfferingId == null)
{
return BadRequest();
return BadRequest("Playlist missing or OfferingId missing");
}

var offering = await _context.Offerings.FindAsync(playlist.OfferingId);

if (offering == null)
{
return BadRequest();
return BadRequest("No such offering");
}

var authorizationResult = await _authorizationService.AuthorizeAsync(this.User, offering, Globals.POLICY_UPDATE_OFFERING);
Expand All @@ -410,28 +411,28 @@ public async Task<ActionResult<Playlist>> PostPlaylist(Playlist playlist)
{
if (User.Identity.IsAuthenticated)
{
return new ForbidResult();
return new ForbidResult("Not authenticated");
}

return new ChallengeResult();
return new ChallengeResult("Not authorized for this offering");
}

if (playlist.PlaylistIdentifier != null && playlist.PlaylistIdentifier.Length > 0)
{
playlist.PlaylistIdentifier = playlist.PlaylistIdentifier.Trim();
}

var p = playlist.ToPlaylist();
// If playlists are deleted the Count != Max Index, so use the max index (still not perfect, what if 2 playlists are created at the same time)
if (offering.Playlists != null && offering.Playlists.Count > 0)
{
playlist.Index = 1 + offering.Playlists.Max(p => p.Index);
p.Index = 1 + offering.Playlists.Max(pl => pl.Index);
}

_context.Playlists.Add(playlist);
_context.Playlists.Add(p);
await _context.SaveChangesAsync();
_wakeDownloader.UpdatePlaylist(playlist.Id);
_wakeDownloader.UpdatePlaylist(p.Id);

return CreatedAtAction("GetPlaylist", new { id = playlist.Id }, playlist);
return await GetPlaylist(p.Id);
}

// DELETE: api/Playlists/5
Expand Down Expand Up @@ -538,6 +539,30 @@ public class PlaylistUpdateDTO {
public JObject Options { get; set; }
public PublishStatus PublishStatus { get; set; }
}

public class NewPlaylistDTO
{
public string OfferingId { get; set; }
public string Name { get; set; }
public SourceType SourceType { get; set; }
public string PlaylistIdentifier { get; set; }
public JObject JsonMetadata { get; set; }
public JObject Options { get; set; }
public PublishStatus PublishStatus { get; set; }

public Playlist ToPlaylist()
{
return new Playlist
{
OfferingId = OfferingId,
Name = Name,
PublishStatus = PublishStatus,
SourceType = SourceType,
JsonMetadata = JsonMetadata,
Options = Options.ToString(Newtonsoft.Json.Formatting.None)
};
}
}
public class PlaylistDTO
{
public string Id { get; set; }
Expand Down
5 changes: 5 additions & 0 deletions ClassTranscribeServer/Controllers/TaskController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
//Future: [Authorize(Roles = Globals.ROLE_MEDIA_WORKER + "," + Globals.ROLE_ADMIN)]
public async Task<ActionResult> UpdateSceneData(string videoId, JObject scene)
{
string sceneAsString = scene.ToString(0);

Check warning on line 49 in ClassTranscribeServer/Controllers/TaskController.cs

View workflow job for this annotation

GitHub Actions / Build

In externally visible method 'Task<ActionResult> TaskController.UpdateSceneData(string videoId, JObject scene)', validate parameter 'scene' is non-null before using it. If appropriate, throw an ArgumentNullException when the argument is null or add a Code Contract precondition asserting non-null argument.
Video video = await _context.Videos.FindAsync(videoId);
var existingScenes = video.HasSceneObjectData();

Expand Down Expand Up @@ -157,6 +157,8 @@
//Future: [Authorize(Roles = Globals.ROLE_MEDIA_WORKER + "," + Globals.ROLE_ADMIN)]
public async Task<ActionResult> UpdatePhraseHints(string videoId, PhraseHintsDTO phraseHintsDTO)
{
if (videoId == null || phraseHintsDTO == null) return BadRequest("Missing parameters");

Video video = await _context.Videos.FindAsync(videoId);
string hints = phraseHintsDTO.PhraseHints ?? "";

Expand All @@ -181,6 +183,8 @@
//Future: [Authorize(Roles = Globals.ROLE_MEDIA_WORKER + "," + Globals.ROLE_ADMIN)]
public async Task<ActionResult> UpdateGlossary(string videoId, JObject glossary)
{
if (videoId == null || glossary == null) return BadRequest("Missing parameters");

string glossaryAsString = glossary.ToString(0);
Video video = await _context.Videos.FindAsync(videoId);
if(video.HasGlossaryData())
Expand Down Expand Up @@ -216,6 +220,7 @@
//Future: [Authorize(Roles = Globals.ROLE_MEDIA_WORKER + "," + Globals.ROLE_ADMIN)]
public async Task<ActionResult> UpdateGlossaryTimestamp(string videoId, JObject glossaryTimestamp)
{
if (videoId == null || glossaryTimestamp == null) return BadRequest("Missing parameters");
string glossaryTimestampAsString = glossaryTimestamp.ToString(0);
Video video = await _context.Videos.FindAsync(videoId);
if(video.HasGlossaryTimestamp())
Expand Down
2 changes: 1 addition & 1 deletion ClassTranscribeServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static IWebHostBuilder CreateWebHostBuilder(string[] args)

string viewSQL = Environment.GetEnvironmentVariable("LogEntityFrameworkSQL") ?? "false";

if( viewSQL.Trim().ToLower() != "true") {
if( viewSQL.Trim().ToUpperInvariant() != "TRUE") {

v.ConfigureLogging((context, logging) => {
logging.AddFilter("Microsoft.EntityFrameworkCore.Database.Command", LogLevel.Warning);
Expand Down
4 changes: 2 additions & 2 deletions TaskEngine/Tasks/DownloadMediaTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@

public async Task<Video> DownloadKalturaVideo(string subdir, Media media)
{
string? swapInfo = media.getOptionsAsJson()?.GetValue("swapStreams")?.ToString();
string? swapInfo = media.GetOptionsAsJson()?.GetValue("swapStreams")?.ToString();

Check warning on line 149 in TaskEngine/Tasks/DownloadMediaTask.cs

View workflow job for this annotation

GitHub Actions / Build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
GetLogger().LogInformation($"DownloadKalturaVideo ({media.Id}): swap streams: {swapInfo}");
bool swapStreams = Boolean.Parse( media.getOptionsAsJson().GetValue("swapStreams").ToString());
bool swapStreams = Boolean.Parse( media.GetOptionsAsJson().GetValue("swapStreams").ToString());
string? video2Url = null;

Check warning on line 152 in TaskEngine/Tasks/DownloadMediaTask.cs

View workflow job for this annotation

GitHub Actions / Build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
string video1Url = media.JsonMetadata["downloadUrl"].ToString();
try {
video2Url = media.JsonMetadata["child"]["downloadUrl"].ToString();
Expand All @@ -158,7 +158,7 @@
video1Url = video2Url;
video2Url = temp;
}
} catch (Exception) { };

Check warning on line 161 in TaskEngine/Tasks/DownloadMediaTask.cs

View workflow job for this annotation

GitHub Actions / Build

Modify 'DownloadKalturaVideo' to catch a more specific allowed exception type, or rethrow the exception.

var mediaResponse = await _rpcClient.PythonServerClient.DownloadKalturaVideoRPCAsync(new CTGrpc.MediaRequest
{
Expand All @@ -184,7 +184,7 @@
video.Video2 = await FileRecord.GetNewFileRecordAsync(childMediaR.FilePath, childMediaR.Ext, subdir);
}
}
} catch(Exception ignored) {

Check warning on line 187 in TaskEngine/Tasks/DownloadMediaTask.cs

View workflow job for this annotation

GitHub Actions / Build

Modify 'DownloadKalturaVideo' to catch a more specific allowed exception type, or rethrow the exception.
GetLogger().LogInformation(ignored, $"Couldnt download second video for {media.Id}");
}
}
Expand Down Expand Up @@ -305,7 +305,7 @@

return video;
}
catch (Exception e)

Check warning on line 308 in TaskEngine/Tasks/DownloadMediaTask.cs

View workflow job for this annotation

GitHub Actions / Build

Modify 'DownloadLocalPlaylist' to catch a more specific allowed exception type, or rethrow the exception.
{
GetLogger().LogError(e, "DownloadLocalPlaylist failed. mediaId {0}", media.Id);
using (var context = CTDbContext.CreateDbContext())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ public async Task Put_Playlist_Success()
var updatedPlaylist = _context.Playlists.Find(playlist.Id);
Assert.Equal(update.Name, updatedPlaylist.Name);
Assert.Equal(update.PublishStatus, updatedPlaylist.PublishStatus);
Assert.Equal(update.Options, updatedPlaylist.getOptionsAsJson());
Assert.Equal(update.Options, updatedPlaylist.GetOptionsAsJson());
Assert.Equal(playlist.SourceType, updatedPlaylist.SourceType);
}

Expand Down Expand Up @@ -322,36 +322,42 @@ public async Task Put_Playlist_Fail()
[Fact]
public async Task Post_Playlist_Success()
{
var playlist = new Playlist
var playlist = new NewPlaylistDTO
{
OfferingId = "offering",
SourceType = SourceType.Local,
Name = "foo",
Index = 0
JsonMetadata = JObject.Parse("{'JM':'XY'}"),
Options =JObject.Parse("{'OptionA':'A'}")
};

_context.Offerings.Add(new Offering { Id = playlist.OfferingId });

var result = await _controller.PostPlaylist(playlist);
Assert.IsType<CreatedAtActionResult>(result.Result);
// Assert.IsType<ActionResult>(result);

var newPlaylist = _context.Playlists.Find(playlist.Id);
Assert.Equal(playlist, newPlaylist);
var newPlaylist = _context.Playlists.Find(result.Value.Id);
Assert.Equal(playlist.Name, newPlaylist.Name);
Assert.Equal(PublishStatus.Published, playlist.PublishStatus);
Assert.Equal(Visibility.Visible, playlist.Visibility);
Assert.Equal(Visibility.Visible, newPlaylist.Visibility);
Assert.Equal(SourceType.Local, newPlaylist.SourceType);
Assert.Equal(playlist.OfferingId, newPlaylist.OfferingId);
Assert.Contains("OptionA", newPlaylist.Options);
Assert.Contains("XY", newPlaylist.JsonMetadata.ToString());

}

[Fact]
public async Task Post_Playlist_Fail()
{
var result = await _controller.PostPlaylist(null);
Assert.IsType<BadRequestResult>(result.Result);
Assert.IsType<BadRequestObjectResult>(result.Result);

result = await _controller.PostPlaylist(new Playlist());
Assert.IsType<BadRequestResult>(result.Result);
result = await _controller.PostPlaylist(new NewPlaylistDTO());
Assert.IsType<BadRequestObjectResult>(result.Result);

result = await _controller.PostPlaylist(new Playlist() { OfferingId = "none" });
Assert.IsType<BadRequestResult>(result.Result);
result = await _controller.PostPlaylist(new NewPlaylistDTO() { OfferingId = "none" });
Assert.IsType<BadRequestObjectResult>(result.Result);
}

[Fact]
Expand Down
Loading