diff --git a/RMuseum/Controllers/RecitationController.cs b/RMuseum/Controllers/RecitationController.cs
index cc684957..f384f4bb 100644
--- a/RMuseum/Controllers/RecitationController.cs
+++ b/RMuseum/Controllers/RecitationController.cs
@@ -258,6 +258,27 @@ namespace RMuseum.Controllers
return Ok(res.Result);
}
+ ///
+ /// Delete a recitation
+ ///
+ ///
+ ///
+ [HttpDelete("{id}")]
+ [Authorize]
+ [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(bool))]
+ [ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
+ [ProducesResponseType((int)HttpStatusCode.Forbidden)]
+ public async Task DeleteRecitation(int id)
+ {
+ Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
+ RServiceResult res = await _audioService.Delete(id, loggedOnUserId);
+ if (!string.IsNullOrEmpty(res.ExceptionString))
+ {
+ return BadRequest(res.ExceptionString);
+ }
+ return Ok(res.Result);
+ }
+
///
@@ -319,7 +340,7 @@ namespace RMuseum.Controllers
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
[ProducesResponseType((int)HttpStatusCode.Forbidden, Type = typeof(string))]
- public async Task ReciationNarrations(bool replace = false)
+ public async Task UploadReciation(bool replace = false)
{
try
{
@@ -469,6 +490,7 @@ namespace RMuseum.Controllers
///
[HttpDelete("profile/{id}")]
+ [Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(bool))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
diff --git a/RMuseum/RMuseum.xml b/RMuseum/RMuseum.xml
index 1cfb6805..64c6928b 100644
--- a/RMuseum/RMuseum.xml
+++ b/RMuseum/RMuseum.xml
@@ -753,6 +753,13 @@
+
+
+ Delete a recitation
+
+
+
+
Get User Uploads
@@ -761,7 +768,7 @@
default: false, user must have narration::moderate permission to be able to see all users uploads
-
+
Reciation Upload
@@ -4973,6 +4980,14 @@
+
+
+ Delete recitation
+
+
+
+
+
Gets Verse Sync Range Information
@@ -5299,6 +5314,14 @@
+
+
+ Delete recitation (recitation should belong to userId)
+
+
+
+
+
Gets Verse Sync Range Information
diff --git a/RMuseum/Services/IRecitationService.cs b/RMuseum/Services/IRecitationService.cs
index e76e2a23..c0caf388 100644
--- a/RMuseum/Services/IRecitationService.cs
+++ b/RMuseum/Services/IRecitationService.cs
@@ -30,6 +30,14 @@ namespace RMuseum.Services
///
Task> Get(int id);
+ ///
+ /// Delete recitation (recitation should belong to userId)
+ ///
+ ///
+ ///
+ ///
+ Task> Delete(int id, Guid userId);
+
///
/// Gets Verse Sync Range Information
///
diff --git a/RMuseum/Services/Implementation/RecitationService.cs b/RMuseum/Services/Implementation/RecitationService.cs
index 76da3265..4e4a75b5 100644
--- a/RMuseum/Services/Implementation/RecitationService.cs
+++ b/RMuseum/Services/Implementation/RecitationService.cs
@@ -97,6 +97,77 @@ namespace RMuseum.Services.Implementation
}
}
+ ///
+ /// Delete recitation
+ ///
+ ///
+ ///
+ ///
+ public async Task> Delete(int id, Guid userId)
+ {
+ try
+ {
+ Recitation recitation = await _context.Recitations.Where(a => a.Id == id && a.OwnerId == userId).FirstOrDefaultAsync();
+ if(recitation == null)
+ {
+ return new RServiceResult(false, "404");
+ }
+
+
+
+ if (recitation.ReviewStatus == AudioReviewStatus.Approved)
+ {
+ recitation.AudioSyncStatus = (int)AudioSyncStatus.Deleted;
+ _context.Recitations.Update(recitation);
+ await _context.SaveChangesAsync();
+
+ _backgroundTaskQueue.QueueBackgroundWorkItem
+ (
+ async token =>
+ {
+ using (RMuseumDbContext context = new RMuseumDbContext(Configuration)) //this is long running job, so _context might be already been freed/collected by GC
+ {
+ await _DeleteNarrationFromRemote(recitation, context);
+ }
+
+
+ });
+ }
+ else
+ {
+ await _FinalizeDelete(_context, recitation);
+ }
+
+
+ return new RServiceResult(true);
+ }
+ catch (Exception exp)
+ {
+ return new RServiceResult(false, exp.ToString());
+ }
+ }
+
+ private async Task _FinalizeDelete(RMuseumDbContext context, Recitation recitation)
+ {
+ try
+ {
+ string mp3 = recitation.LocalMp3FilePath;
+ string xml = recitation.LocalXmlFilePath;
+ context.Recitations.Remove(recitation);
+ await context.SaveChangesAsync();
+
+ File.Delete(mp3);
+ File.Delete(xml);
+
+ return "";
+ }
+ catch(Exception exp)
+ {
+ return exp.ToString();
+ }
+ }
+
+
///
/// Gets Verse Sync Range Information
///
@@ -945,6 +1016,58 @@ namespace RMuseum.Services.Implementation
}
}
+ private async Task _DeleteNarrationFromRemote(Recitation narration, RMuseumDbContext context)
+ {
+ using var client = new SftpClient
+ (
+ Configuration.GetSection("AudioSFPServer")["Host"],
+ int.Parse(Configuration.GetSection("AudioSFPServer")["Port"]),
+ Configuration.GetSection("AudioSFPServer")["Username"],
+ Configuration.GetSection("AudioSFPServer")["Password"]
+ );
+ try
+ {
+ client.Connect();
+ client.DeleteFile($"{Configuration.GetSection("AudioSFPServer")["RootPath"]}{narration.RemoteXMLFilePath}");
+ client.DeleteFile($"{Configuration.GetSection("AudioSFPServer")["RootPath"]}{narration.RemoteMp3FilePath}");
+
+
+
+ string sql = $"DELETE FROM ganja_gaudio WHERE audio_post_ID = {narration.GanjoorPostId} AND audio_order = {narration.AudioOrder} AND audio_guid = '{narration.LegacyAudioGuid}'";
+
+ using (MySqlConnection connection = new MySqlConnection
+ (
+ $"server={Configuration.GetSection("AudioMySqlServer")["Server"]};uid={Configuration.GetSection("AudioMySqlServer")["Username"]};pwd={Configuration.GetSection("AudioMySqlServer")["Password"]};database={Configuration.GetSection("AudioMySqlServer")["Database"]};charset=utf8"
+ ))
+ {
+ await connection.OpenAsync();
+ await connection.ExecuteAsync(sql);
+ }
+
+ //We are using two database for different purposes on the remote
+ using (MySqlConnection connection = new MySqlConnection
+ (
+ $"server={Configuration.GetSection("AudioMySqlServer")["Server"]};uid={Configuration.GetSection("AudioMySqlServer")["2ndUsername"]};pwd={Configuration.GetSection("AudioMySqlServer")["2ndPassword"]};database={Configuration.GetSection("AudioMySqlServer")["2ndDatabase"]};charset=utf8"
+ ))
+ {
+ await connection.OpenAsync();
+ await connection.ExecuteAsync(sql);
+ }
+
+ await _FinalizeDelete(context, narration);
+
+
+ }
+ catch
+ {
+ //if an error occurs, narration.AudioSyncStatus is not updated and narration can be idetified later to do "retrypublish" attempts
+ }
+ finally
+ {
+ client.Disconnect();
+ }
+ }
+
///
/// retry publish unpublished narrations
///