diff --git a/RMuseum/Controllers/PDFLibraryController.cs b/RMuseum/Controllers/PDFLibraryController.cs
new file mode 100644
index 00000000..add8596a
--- /dev/null
+++ b/RMuseum/Controllers/PDFLibraryController.cs
@@ -0,0 +1,237 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using RMuseum.Models.Artifact;
+using RMuseum.Models.Auth.Memory;
+using RMuseum.Models.PDFLibrary;
+using RMuseum.Models.PDFLibrary.ViewModels;
+using RMuseum.Services;
+using RSecurityBackend.Models.Auth.Memory;
+using RSecurityBackend.Models.Generic;
+using System.Linq;
+using System;
+using System.Net;
+using System.Threading.Tasks;
+using RSecurityBackend.Services;
+
+namespace RMuseum.Controllers
+{
+ [Produces("application/json")]
+ [Route("api/pdf")]
+ public class PDFLibraryController : Controller
+ {
+ ///
+ /// start importing a local pdf file
+ ///
+ ///
+ ///
+ [HttpPost]
+ [Authorize(Policy = RMuseumSecurableItem.PDFLibraryEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
+ [ProducesResponseType((int)HttpStatusCode.OK)]
+ [ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
+ public IActionResult StartImportingLocalPDF([FromBody] NewPDFBookViewModel model)
+ {
+ var res = _pdfService.StartImportingLocalPDF(model);
+ if (!string.IsNullOrEmpty(res.ExceptionString))
+ return BadRequest(res.ExceptionString);
+ return Ok();
+ }
+
+ ///
+ /// secure get a pdf book
+ ///
+ ///
+ ///
+ [HttpGet("secure/{id}")]
+ [Authorize]
+ [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(PDFBook))]
+ [ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
+ [ProducesResponseType((int)HttpStatusCode.NotFound)]
+ public async Task GetUserVisible(int id)
+ {
+ RServiceResult v = await _GetUserVisibleArtifactStatusSet
+ (
+ new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value),
+ new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value)
+ );
+ if (!string.IsNullOrEmpty(v.ExceptionString))
+ return BadRequest(v.ExceptionString);
+ PublishStatus[] visibleItems = v.Result;
+ RServiceResult bookRes = null;
+ if (visibleItems.Length == 1 && visibleItems[0] == PublishStatus.Published)
+ {
+ bookRes = await _pdfService.GetPDFBookByIdAsync(id, new PublishStatus[] { PublishStatus.Published });
+ if (!string.IsNullOrEmpty(bookRes.ExceptionString))
+ {
+ return BadRequest(bookRes.ExceptionString);
+ }
+ if (bookRes.Result == null)
+ return NotFound();
+ }
+ if (bookRes == null)
+ {
+ bookRes = await _pdfService.GetPDFBookByIdAsync(id, visibleItems);
+ }
+
+ if (!string.IsNullOrEmpty(bookRes.ExceptionString))
+ {
+ return BadRequest(bookRes.ExceptionString);
+ }
+ if (bookRes.Result == null)
+ return NotFound();
+
+ Response.GetTypedHeaders().LastModified = bookRes.Result.LastModified;
+
+ var requestHeaders = Request.GetTypedHeaders();
+ if (requestHeaders.IfModifiedSince.HasValue &&
+ requestHeaders.IfModifiedSince.Value >= bookRes.Result.LastModified)
+ {
+ return StatusCode(StatusCodes.Status304NotModified);
+ }
+
+
+ return Ok(bookRes.Result);
+ }
+
+ private async Task> _GetUserVisibleArtifactStatusSet(Guid loggedOnUserId, Guid sessionId)
+ {
+ RServiceResult
+ canView =
+ await _userPermissionChecker.Check
+ (
+ loggedOnUserId,
+ sessionId,
+ RMuseumSecurableItem.PDFLibraryEntityShortName,
+ RMuseumSecurableItem.ViewDraftOperationShortName
+ );
+ if (!string.IsNullOrEmpty(canView.ExceptionString))
+ return new RServiceResult(null, canView.ExceptionString);
+
+ PublishStatus[] visibleItems =
+ canView.Result
+ ?
+ new PublishStatus[]
+ {
+ PublishStatus.Published,
+ PublishStatus.Restricted,
+ PublishStatus.Draft,
+ PublishStatus.Awaiting
+ }
+ :
+ new PublishStatus[]
+ {
+ PublishStatus.Published
+ };
+
+ return new RServiceResult(visibleItems);
+ }
+
+ ///
+ /// get published PDF Book by id
+ ///
+ ///
+ ///
+ [HttpGet("{id}")]
+ [AllowAnonymous]
+ [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(PDFBook))]
+ [ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
+ [ProducesResponseType((int)HttpStatusCode.NotFound)]
+ public async Task GetPDFBookByIdAsync(int id)
+ {
+ var bookRes = await _pdfService.GetPDFBookByIdAsync(id, new PublishStatus[] { PublishStatus.Published });
+
+ if (!string.IsNullOrEmpty(bookRes.ExceptionString))
+ {
+ return BadRequest(bookRes.ExceptionString);
+ }
+ if (bookRes.Result == null)
+ return NotFound();
+
+ Response.GetTypedHeaders().LastModified = bookRes.Result.LastModified;
+
+ var requestHeaders = Request.GetTypedHeaders();
+ if (requestHeaders.IfModifiedSince.HasValue &&
+ requestHeaders.IfModifiedSince.Value >= bookRes.Result.LastModified)
+ {
+ return StatusCode(StatusCodes.Status304NotModified);
+ }
+
+
+ return Ok(bookRes.Result);
+ }
+
+ ///
+ /// add a new book
+ ///
+ ///
+ ///
+
+ [HttpPost("book")]
+ [Authorize(Policy = RMuseumSecurableItem.PDFLibraryEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
+ [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(Book))]
+ [ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
+ public async Task AddBookAsync([FromBody] Book book)
+ {
+ var res = await _pdfService.AddBookAsync(book);
+ if (!string.IsNullOrEmpty(res.ExceptionString))
+ return BadRequest(res.ExceptionString);
+ return Ok(res.Result);
+ }
+
+ ///
+ /// add a new author
+ ///
+ ///
+ ///
+
+ [HttpPost("author")]
+ [Authorize(Policy = RMuseumSecurableItem.PDFLibraryEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
+ [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(Author))]
+ [ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
+ public async Task AddAuthorAsync([FromBody] Author author)
+ {
+ var res = await _pdfService.AddAuthorAsync(author);
+ if (!string.IsNullOrEmpty(res.ExceptionString))
+ return BadRequest(res.ExceptionString);
+ return Ok(res.Result);
+ }
+
+ ///
+ /// add a new mukti volume pdf collection
+ ///
+ ///
+ ///
+ [HttpPost("volumes")]
+ [Authorize(Policy = RMuseumSecurableItem.PDFLibraryEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
+ [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(MultiVolumePDFCollection))]
+ [ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
+ public async Task AddMultiVolumePDFCollection([FromBody] MultiVolumePDFCollection volumes)
+ {
+ var res = await _pdfService.AddMultiVolumePDFCollection(volumes);
+ if (!string.IsNullOrEmpty(res.ExceptionString))
+ return BadRequest(res.ExceptionString);
+ return Ok(res.Result);
+ }
+
+ ///
+ /// PDF Service
+ ///
+ protected readonly IPDFLibraryService _pdfService;
+
+ ///
+ /// IUserPermissionChecker instance
+ ///
+ protected IUserPermissionChecker _userPermissionChecker;
+
+ ///
+ /// constructor
+ ///
+ ///
+ ///
+ public PDFLibraryController(IPDFLibraryService pdfService, IUserPermissionChecker userPermissionChecker)
+ {
+ _pdfService = pdfService;
+ _userPermissionChecker = userPermissionChecker;
+ }
+ }
+}
diff --git a/RMuseum/Models/Auth/Memory/RMuseumSecurableItem.cs b/RMuseum/Models/Auth/Memory/RMuseumSecurableItem.cs
index d1c8e9cc..4b104c18 100644
--- a/RMuseum/Models/Auth/Memory/RMuseumSecurableItem.cs
+++ b/RMuseum/Models/Auth/Memory/RMuseumSecurableItem.cs
@@ -108,6 +108,11 @@ namespace RMuseum.Models.Auth.Memory
///
public const string ModeratePoetPhotos = "photos";
+ ///
+ /// pdf
+ ///
+ public const string PDFLibraryEntityShortName = "pdf";
+
///
/// list of forms and their permissions
///
@@ -194,6 +199,16 @@ namespace RMuseum.Models.Auth.Memory
new SecurableItemOperation(ModerateOperationShortName, "مدیریت", false),
}
},
+ new SecurableItem()
+ {
+ ShortName = PDFLibraryEntityShortName,
+ Description = "نسکبان",
+ Operations = new SecurableItemOperation[]
+ {
+ new SecurableItemOperation(ModifyOperationShortName, "ویرایش محتوا", false),
+ new SecurableItemOperation(ViewDraftOperationShortName, "مشاهدهٔ پیشنویسها", false),
+ }
+ },
diff --git a/RMuseum/RMuseum.xml b/RMuseum/RMuseum.xml
index 388514db..b166feed 100644
--- a/RMuseum/RMuseum.xml
+++ b/RMuseum/RMuseum.xml
@@ -2343,6 +2343,65 @@
+
+
+ start importing a local pdf file
+
+
+
+
+
+
+ secure get a pdf book
+
+
+
+
+
+
+ get published PDF Book by id
+
+
+
+
+
+
+ add a new book
+
+
+
+
+
+
+ add a new author
+
+
+
+
+
+
+ add a new mukti volume pdf collection
+
+
+
+
+
+
+ PDF Service
+
+
+
+
+ IUserPermissionChecker instance
+
+
+
+
+ constructor
+
+
+
+
returns paginated published recitations (if poetId or catId is non-zero its ordered by poemId ascending if not it is ordered by publish date descending)
@@ -4387,6 +4446,11 @@
photos
+
+
+ pdf
+
+
list of forms and their permissions
@@ -17424,6 +17488,14 @@
طول تصویر بندانگشتی
+
+
+ get pdf book by id
+
+
+
+
+
start importing local pdf file
@@ -17431,6 +17503,42 @@
+
+
+ add author
+
+
+
+
+
+
+ get author by id
+
+
+
+
+
+
+ get authors
+
+
+
+
+
+
+
+ add book
+
+
+
+
+
+
+ add multi volume pdf collection
+
+
+
+
Database Context
@@ -18234,6 +18342,50 @@
PDF Library Services
+
+
+ get pdf book by id
+
+
+
+
+
+
+
+ add author
+
+
+
+
+
+
+ get author by id
+
+
+
+
+
+
+ get authors
+
+
+
+
+
+
+
+ add book
+
+
+
+
+
+
+ add multi volume pdf collection
+
+
+
+
start importing local pdf file
diff --git a/RMuseum/Services/IPDFLibraryService.cs b/RMuseum/Services/IPDFLibraryService.cs
index 05e70a30..c98bbf36 100644
--- a/RMuseum/Services/IPDFLibraryService.cs
+++ b/RMuseum/Services/IPDFLibraryService.cs
@@ -1,5 +1,8 @@
-using RMuseum.Models.PDFLibrary.ViewModels;
+using RMuseum.Models.Artifact;
+using RMuseum.Models.PDFLibrary;
+using RMuseum.Models.PDFLibrary.ViewModels;
using RSecurityBackend.Models.Generic;
+using System.Threading.Tasks;
namespace RMuseum.Services
{
@@ -8,6 +11,50 @@ namespace RMuseum.Services
///
public interface IPDFLibraryService
{
+ ///
+ /// get pdf book by id
+ ///
+ ///
+ ///
+ ///
+ Task> GetPDFBookByIdAsync(int id, PublishStatus[] statusArray);
+
+ ///
+ /// add author
+ ///
+ ///
+ ///
+ Task> AddAuthorAsync(Author author);
+
+ ///
+ /// get author by id
+ ///
+ ///
+ ///
+ Task> GetAuthorByIdAsync(int id);
+
+ ///
+ /// get authors
+ ///
+ ///
+ ///
+ ///
+ Task> GetAuthorsAsync(PagingParameterModel paging, string authorName);
+
+ ///
+ /// add book
+ ///
+ ///
+ ///
+ Task> AddBookAsync(Book book);
+
+ ///
+ /// add multi volume pdf collection
+ ///
+ ///
+ ///
+ Task> AddMultiVolumePDFCollection(MultiVolumePDFCollection multiVolumePDFCollection);
+
///
/// start importing local pdf file
///
diff --git a/RMuseum/Services/Implementation/PDFLibraryService-Partials/PDFLibraryService-LocalPDF.cs b/RMuseum/Services/Implementation/PDFLibraryService-Partials/PDFLibraryService-LocalPDF.cs
index f81cdb20..d0b438ca 100644
--- a/RMuseum/Services/Implementation/PDFLibraryService-Partials/PDFLibraryService-LocalPDF.cs
+++ b/RMuseum/Services/Implementation/PDFLibraryService-Partials/PDFLibraryService-LocalPDF.cs
@@ -20,7 +20,7 @@ namespace RMuseum.Services.Implementation
{
public partial class PDFLibraryService
{
- private async Task> ImportLocalPDFFile(RMuseumDbContext context, int bookId, int? volumeId, int volumeOrder, string filePath, string srcUrl, bool skipUpload)
+ private async Task> ImportLocalPDFFileAsync(RMuseumDbContext context, int bookId, int? volumeId, int volumeOrder, string filePath, string srcUrl, bool skipUpload)
{
string fileChecksum = PoemAudio.ComputeCheckSum(filePath);
if (
diff --git a/RMuseum/Services/Implementation/PDFLibraryService.cs b/RMuseum/Services/Implementation/PDFLibraryService.cs
index d10fc17c..a8852b72 100644
--- a/RMuseum/Services/Implementation/PDFLibraryService.cs
+++ b/RMuseum/Services/Implementation/PDFLibraryService.cs
@@ -1,12 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using RMuseum.DbContext;
+using RMuseum.Models.Artifact;
using RMuseum.Models.PDFLibrary;
using RMuseum.Models.PDFLibrary.ViewModels;
using RSecurityBackend.Models.Generic;
using RSecurityBackend.Services;
+using RSecurityBackend.Services.Implementation;
+using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
namespace RMuseum.Services.Implementation
{
@@ -15,6 +19,32 @@ namespace RMuseum.Services.Implementation
///
public partial class PDFLibraryService : IPDFLibraryService
{
+ ///
+ /// get pdf book by id
+ ///
+ ///
+ ///
+ ///
+ public async Task> GetPDFBookByIdAsync(int id, PublishStatus[] statusArray)
+ {
+ try
+ {
+ var pdfBook = await _context.PDFBooks.AsNoTracking()
+ .Include(b => b.Book)
+ .Include(b => b.MultiVolumePDFCollection)
+ .Include(b => b.Contributers)
+ .Include(b => b.Tags)
+ .Include(b => b.Pages)
+ .Where(b => statusArray.Contains(b.Status) &&b.Id == id)
+ .SingleOrDefaultAsync();
+ return new RServiceResult(pdfBook);
+
+ }
+ catch (Exception exp)
+ {
+ return new RServiceResult(null, exp.ToString());
+ }
+ }
///
/// start importing local pdf file
@@ -29,7 +59,7 @@ namespace RMuseum.Services.Implementation
{
using (RMuseumDbContext context = new RMuseumDbContext(new DbContextOptions()))
{
- var pdfRes = await ImportLocalPDFFile(context, model.BookId, model.MultiVolumePDFCollectionId, model.VolumeOrder, model.LocalImportingPDFFilePath, model.OriginalSourceUrl, model.SkipUpload);
+ var pdfRes = await ImportLocalPDFFileAsync(context, model.BookId, model.MultiVolumePDFCollectionId, model.VolumeOrder, model.LocalImportingPDFFilePath, model.OriginalSourceUrl, model.SkipUpload);
if (pdfRes.Result != null)
{
var pdfBook = pdfRes.Result;
@@ -49,7 +79,7 @@ namespace RMuseum.Services.Implementation
pdfBook.OriginalSourceName = model.OriginalSourceName;
pdfBook.OriginalFileUrl = model.OriginalFileUrl;
List roles = new List();
- if(model.WriterId != null)
+ if (model.WriterId != null)
{
roles.Add(new AuthorRole()
{
@@ -81,7 +111,7 @@ namespace RMuseum.Services.Implementation
Role = "نویسنده",
});
}
- if(model.TranslatorId != null)
+ if (model.TranslatorId != null)
{
roles.Add(new AuthorRole()
{
@@ -129,7 +159,7 @@ namespace RMuseum.Services.Implementation
Role = "مصحح",
});
}
- if(roles.Count > 0)
+ if (roles.Count > 0)
{
pdfBook.Contributers = roles;
}
@@ -137,35 +167,118 @@ namespace RMuseum.Services.Implementation
await context.SaveChangesAsync();
}
}
-
}
);
-
-
return new RServiceResult(true);
}
+ ///
+ /// add author
+ ///
+ ///
+ ///
+ public async Task> AddAuthorAsync(Author author)
+ {
+ try
+ {
+ _context.Add(author);
+ await _context.SaveChangesAsync();
+ return new RServiceResult(author);
+ }
+ catch (Exception exp)
+ {
+ return new RServiceResult(null, exp.ToString());
+ }
+ }
+
+ ///
+ /// get author by id
+ ///
+ ///
+ ///
+ public async Task> GetAuthorByIdAsync(int id)
+ {
+ try
+ {
+ return new RServiceResult(await _context.Authors.AsNoTracking().Where(a => a.Id == id).SingleOrDefaultAsync());
+ }
+ catch (Exception exp)
+ {
+ return new RServiceResult(null, exp.ToString());
+ }
+ }
+
+ ///
+ /// get authors
+ ///
+ ///
+ ///
+ ///
+ public async Task> GetAuthorsAsync(PagingParameterModel paging, string authorName)
+ {
+ var source =
+ _context.Authors
+ .Where(a => string.IsNullOrEmpty(authorName) || (authorName.Contains(a.Name) || (!string.IsNullOrEmpty(a.NameInOriginalLanguage) && authorName.Contains(a.NameInOriginalLanguage)) ))
+ .AsQueryable();
+ (PaginationMetadata PagingMeta, Author[] Items) paginatedResult =
+ await QueryablePaginator.Paginate(source, paging);
+ return new RServiceResult<(PaginationMetadata PagingMeta, Author[] Authors)>(paginatedResult);
+ }
+
+ ///
+ /// add book
+ ///
+ ///
+ ///
+ public async Task> AddBookAsync(Book book)
+ {
+ try
+ {
+ _context.Add(book);
+ await _context.SaveChangesAsync();
+ return new RServiceResult(book);
+ }
+ catch (Exception exp)
+ {
+ return new RServiceResult(null, exp.ToString());
+ }
+ }
+
+ ///
+ /// add multi volume pdf collection
+ ///
+ ///
+ ///
+ public async Task> AddMultiVolumePDFCollection(MultiVolumePDFCollection multiVolumePDFCollection)
+ {
+ try
+ {
+ _context.Add(multiVolumePDFCollection);
+ await _context.SaveChangesAsync();
+ return new RServiceResult(multiVolumePDFCollection);
+ }
+ catch (Exception exp)
+ {
+ return new RServiceResult(null, exp.ToString());
+ }
+ }
+
///
/// Database Context
///
protected readonly RMuseumDbContext _context;
-
///
/// Background Task Queue Instance
///
protected readonly IBackgroundTaskQueue _backgroundTaskQueue;
-
///
/// image file service
///
protected readonly IImageFileService _imageFileService;
-
///
/// Configuration
///
protected IConfiguration Configuration { get; }
-
-
///
/// constructor
///