using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using RMuseum.Models.Artifact;
using RMuseum.Models.Artifact.ViewModels;
using RMuseum.Models.Auth.Memory;
using RMuseum.Models.Bookmark;
using RMuseum.Models.Bookmark.ViewModels;
using RMuseum.Models.DivanIntegration;
using RMuseum.Models.DivanIntegration.ViewModels;
using RMuseum.Models.ImportJob;
using RMuseum.Models.Note;
using RMuseum.Models.Note.ViewModels;
using RMuseum.Services;
using RSecurityBackend.Models.Auth.Memory;
using RSecurityBackend.Models.Generic;
using RSecurityBackend.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
namespace RMuseum.Controllers
{
[Produces("application/json")]
[Route("api/artifacts")]
public class ArtifactController : Controller
{
///
/// HTTP dates only have one-second precision - truncate before using a value for
/// Last-Modified/If-Modified-Since comparisons, or a DB value with sub-second precision
/// would always fail the >= comparison against a client's necessarily-truncated header
///
///
///
private static DateTime TruncateToSeconds(DateTime dt)
{
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Kind);
}
///
/// gets specified publish artifact item info (including images + attributes)
///
///
///
///
[HttpGet("{artifactUrl}/{itemUrl}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactItemRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetArtifactItemByFrienlyUrl(string artifactUrl, string itemUrl)
{
RServiceResult itemInfo = await _artifactService.GetArtifactItemByFrienlyUrl(artifactUrl, itemUrl, new PublishStatus[] { PublishStatus.Published });
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo.Result == null)
return NotFound();
Response.GetTypedHeaders().LastModified = TruncateToSeconds(itemInfo.Result.Item.LastModified);
Response.Headers.CacheControl = "public,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(itemInfo.Result.Item.LastModified))
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(itemInfo.Result);
}
///
/// get all published artifacts (including CoverImage info but not items info)
///
///
///
[HttpGet]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(IEnumerable))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task Get([FromQuery] PagingParameterModel paging)
{
var cacheKey = $"artifacts/all/{paging.PageSize}/{paging.PageNumber}";
if (!_memoryCache.TryGetValue(cacheKey, out RServiceResult<(PaginationMetadata PagingMeta, RArtifactMasterRecord[] Items)> itemsInfo))
{
itemsInfo = await _artifactService.GetAll(paging, new PublishStatus[] { PublishStatus.Published });
if (!string.IsNullOrEmpty(itemsInfo.ExceptionString))
{
return BadRequest(itemsInfo.ExceptionString);
}
_memoryCache.Set(cacheKey, itemsInfo, TimeSpan.FromHours(1));
}
if (itemsInfo.Result.Items.Count() > 0)
{
DateTime lastModification = itemsInfo.Result.Items.Max(i => i.LastModified);
Response.GetTypedHeaders().LastModified = TruncateToSeconds(lastModification);
Response.Headers.CacheControl = "public,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(lastModification))
{
return StatusCode(StatusCodes.Status304NotModified);
}
}
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(itemsInfo.Result.PagingMeta));
return Ok(itemsInfo.Result.Items);
}
///
/// get list of artifact statuses user can see
///
///
///
///
private async Task> _GetUserVisibleArtifactStatusSet(Guid loggedOnUserId, Guid sessionId)
{
RServiceResult
canView =
await _userPermissionChecker.Check
(
loggedOnUserId,
sessionId,
User.Claims.Any(c => c.Type == "Language") ? User.Claims.First(c => c.Type == "Language").Value : "ur-PK",
RMuseumSecurableItem.ArtifactEntityShortName,
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 all artifacts visible by user (including CoverImage info but not items info)
///
///
///
[HttpGet]
[Route("secure")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(IEnumerable))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetUserVisible([FromQuery] PagingParameterModel paging)
{
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;
if (visibleItems.Length == 1 && visibleItems[0] == PublishStatus.Published) //Caching
{
return await Get(paging);
}
RServiceResult<(PaginationMetadata PagingMeta, RArtifactMasterRecord[] Items)> itemsInfo = await _artifactService.GetAll(paging, visibleItems);
if (!string.IsNullOrEmpty(itemsInfo.ExceptionString))
{
return BadRequest(itemsInfo.ExceptionString);
}
if (itemsInfo.Result.Items.Count() > 0)
{
DateTime lastModification = itemsInfo.Result.Items.Max(i => i.LastModified);
Response.GetTypedHeaders().LastModified = TruncateToSeconds(lastModification);
Response.Headers.CacheControl = "private,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(lastModification))
{
return StatusCode(StatusCodes.Status304NotModified);
}
}
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(itemsInfo.Result.PagingMeta));
return Ok(itemsInfo.Result.Items);
}
[HttpGet("tagged/{tagUrl}/{valueUrl}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(IEnumerable))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetByTagValue(string tagUrl, string valueUrl)
{
RServiceResult itemsInfo = await _artifactService.GetByTagValue(tagUrl, valueUrl, new PublishStatus[] { PublishStatus.Published });
if (!string.IsNullOrEmpty(itemsInfo.ExceptionString))
{
return BadRequest(itemsInfo.ExceptionString);
}
if (itemsInfo.Result.Length > 0)
{
DateTime lastModification = itemsInfo.Result.Max(i => i.LastModified);
Response.GetTypedHeaders().LastModified = TruncateToSeconds(lastModification);
Response.Headers.CacheControl = "public,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(lastModification))
{
return StatusCode(StatusCodes.Status304NotModified);
}
}
return Ok(itemsInfo.Result);
}
///
/// gets specified publish artifact info (including CoverImage + images)
///
///
///
[HttpGet("{friendlyUrl}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactMasterRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task Get(string friendlyUrl)
{
var cacheKey = $"artifacts/friendlyUrl/{friendlyUrl}";
if (!_memoryCache.TryGetValue(cacheKey, out RServiceResult itemInfo))
{
itemInfo = await _artifactService.GetByFriendlyUrl(friendlyUrl, new PublishStatus[] { PublishStatus.Published });
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo.Result == null)
return NotFound();
_memoryCache.Set(cacheKey, itemInfo, TimeSpan.FromHours(1));
}
Response.GetTypedHeaders().LastModified = TruncateToSeconds(itemInfo.Result.LastModified);
Response.Headers.CacheControl = "public,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(itemInfo.Result.LastModified))
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(itemInfo.Result);
}
///
/// get specific artifact info with limited number of images
///
///
///
///
[HttpGet("limited/{friendlyUrl}/{count}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactMasterRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetByFriendlyUrlLimitedItemsAsync(string friendlyUrl, int count = 21)
{
var cacheKey = $"artifacts/friendlyUrl/limited/{friendlyUrl}/{count}";
if (!_memoryCache.TryGetValue(cacheKey, out RServiceResult itemInfo))
{
itemInfo = await _artifactService.GetByFriendlyUrlLimitedItemsAsync(friendlyUrl, [PublishStatus.Published], count);
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo.Result == null)
return NotFound();
_memoryCache.Set(cacheKey, itemInfo, TimeSpan.FromHours(1));
}
Response.GetTypedHeaders().LastModified = TruncateToSeconds(itemInfo.Result.LastModified);
Response.Headers.CacheControl = "public,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(itemInfo.Result.LastModified))
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(itemInfo.Result);
}
///
/// get artifact images according to start and count params
///
///
///
///
///
[HttpGet("itemsof/{id}/{start}/{count}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactMasterRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetArtifactItemsAsync(Guid id, int start, int count = 21)
{
var result = await _artifactService.GetArtifactItemsAsync(id, start, count);
if(!string.IsNullOrEmpty(result.ExceptionString))
return BadRequest(result.ExceptionString);
return Ok(result.Result);
}
///
/// remove unpublished artifact having no notes and not bookmarked
///
///
///
[HttpDelete("{artifactId}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + SecurableItem.DeleteOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(bool))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
public async Task RemoveArtifact(Guid artifactId)
{
RServiceResult res = await _artifactService.RemoveArtifact(artifactId, true);
if (!string.IsNullOrEmpty(res.ExceptionString))
{
return BadRequest(res.ExceptionString);
}
return Ok(res.Result);
}
///
/// gets specified publish artifact info (including CoverImage + images) where its items are filteted by tag
///
///
///
///
[HttpGet("{friendlyUrl}/filteritemsbytag/{tagFriendlyUrl}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactMasterRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetByFriendlyUrlFilterItemsByTag(string friendlyUrl, string tagFriendlyUrl)
{
return await GetByFriendlyUrlFilterItemsByTag(friendlyUrl, tagFriendlyUrl, null);
}
///
/// gets specified publish artifact info (including CoverImage + images) where its items are filteted by tag
///
///
///
///
///
[HttpGet("{friendlyUrl}/filteritemsbytag/{tagFriendlyUrl}/{valueFriendlyUrl}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactMasterRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetByFriendlyUrlFilterItemsByTag(string friendlyUrl, string tagFriendlyUrl, string valueFriendlyUrl)
{
var cacheKey = $"{friendlyUrl}/filteritemsbytag/{tagFriendlyUrl}";
if (valueFriendlyUrl != null)
{
cacheKey += $"/{valueFriendlyUrl}";
}
if (!_memoryCache.TryGetValue(cacheKey, out RServiceResult itemInfo))
{
itemInfo = await _artifactService.GetByFriendlyUrlFilterItemsByTag(friendlyUrl, new PublishStatus[] { PublishStatus.Published }, tagFriendlyUrl, valueFriendlyUrl);
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo.Result == null)
return NotFound();
_memoryCache.Set(cacheKey, itemInfo, TimeSpan.FromHours(1));
}
Response.GetTypedHeaders().LastModified = TruncateToSeconds(itemInfo.Result.LastModified);
Response.Headers.CacheControl = "public,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(itemInfo.Result.LastModified))
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(itemInfo.Result);
}
///
/// gets specified publish artifact info (including CoverImage + images)
///
///
///
[HttpGet("secure/{friendlyUrl}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactMasterRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetUserVisible(string friendlyUrl)
{
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 itemInfo = null;
if (visibleItems.Length == 1 && visibleItems[0] == PublishStatus.Published)
{
var cacheKey = $"artifacts/friendlyUrl/{friendlyUrl}";
if (!_memoryCache.TryGetValue(cacheKey, out itemInfo))
{
itemInfo = await _artifactService.GetByFriendlyUrl(friendlyUrl, new PublishStatus[] { PublishStatus.Published });
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo.Result == null)
return NotFound();
_memoryCache.Set(cacheKey, itemInfo, TimeSpan.FromHours(1));
}
}
if (itemInfo == null)
{
itemInfo = await _artifactService.GetByFriendlyUrl(friendlyUrl, visibleItems);
}
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo.Result == null)
return NotFound();
Response.GetTypedHeaders().LastModified = TruncateToSeconds(itemInfo.Result.LastModified);
Response.Headers.CacheControl = "private,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(itemInfo.Result.LastModified))
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(itemInfo.Result);
}
///
/// gets specified publish artifact info (including CoverImage + images)
///
///
///
///
[HttpGet("secure/limited/{friendlyUrl}/{count}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactMasterRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetUserVisibleLimitedItemsAsync(string friendlyUrl, int count = 21)
{
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 itemInfo = null;
if (visibleItems.Length == 1 && visibleItems[0] == PublishStatus.Published)
{
var cacheKey = $"artifacts/friendlyUrl/limited/{friendlyUrl}/{count}";
if (!_memoryCache.TryGetValue(cacheKey, out itemInfo))
{
itemInfo = await _artifactService.GetByFriendlyUrlLimitedItemsAsync(friendlyUrl, [PublishStatus.Published], count);
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo.Result == null)
return NotFound();
_memoryCache.Set(cacheKey, itemInfo, TimeSpan.FromHours(1));
}
}
if (itemInfo == null)
{
itemInfo = await _artifactService.GetByFriendlyUrlLimitedItemsAsync(friendlyUrl, visibleItems, count);
}
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo.Result == null)
return NotFound();
Response.GetTypedHeaders().LastModified = TruncateToSeconds(itemInfo.Result.LastModified);
Response.Headers.CacheControl = "private,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(itemInfo.Result.LastModified))
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(itemInfo.Result);
}
///
/// gets specified publish artifact info (including CoverImage + images) where its items are filteted by tag
///
///
///
///
[HttpGet("secure/{friendlyUrl}/filteritemsbytag/{tagFriendlyUrl}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactMasterRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetUserVisibleByFriendlyUrlFilterItemsByTag(string friendlyUrl, string tagFriendlyUrl)
{
return await GetUserVisibleByFriendlyUrlFilterItemsByTag(friendlyUrl, tagFriendlyUrl, null);
}
///
/// gets specified publish artifact info (including CoverImage + images) where its items are filteted by tag
///
///
///
///
///
[HttpGet("secure/{friendlyUrl}/filteritemsbytag/{tagFriendlyUrl}/{valueFriendlyUrl}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactMasterRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetUserVisibleByFriendlyUrlFilterItemsByTag(string friendlyUrl, string tagFriendlyUrl, string valueFriendlyUrl)
{
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;
if (visibleItems.Length == 1 && visibleItems[0] == PublishStatus.Published)
{
return await GetByFriendlyUrlFilterItemsByTag(friendlyUrl, tagFriendlyUrl, valueFriendlyUrl);
}
RServiceResult itemInfo = await _artifactService.GetByFriendlyUrlFilterItemsByTag(friendlyUrl, visibleItems, tagFriendlyUrl, valueFriendlyUrl);
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo.Result == null)
return NotFound();
Response.GetTypedHeaders().LastModified = TruncateToSeconds(itemInfo.Result.LastModified);
Response.Headers.CacheControl = "private,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(itemInfo.Result.LastModified))
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(itemInfo.Result);
}
///
/// edit artifactt master record (user should have additional permissions artifact:awaiting and artifact:publish to change status of artifact)
///
///
/// editing related collections such as images and attributed or complex properties such as CoverImage is ignored
///
///
///
///
[HttpPut("{id}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task Put(Guid id, [FromBody] RArtifactMasterRecord item)
{
if (id != item.Id)
{
return BadRequest();
}
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
Guid sessionId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value);
RServiceResult
canChangeStatusToAwaiting =
await _userPermissionChecker.Check
(
loggedOnUserId,
sessionId,
User.Claims.Any(c => c.Type == "Language") ? User.Claims.First(c => c.Type == "Language").Value : "ur-PK",
RMuseumSecurableItem.ArtifactEntityShortName,
RMuseumSecurableItem.ToAwaitingStatusOperationShortName
);
if (!string.IsNullOrEmpty(canChangeStatusToAwaiting.ExceptionString))
return BadRequest(canChangeStatusToAwaiting.ExceptionString);
RServiceResult
canPublish =
await _userPermissionChecker.Check
(
loggedOnUserId,
sessionId,
User.Claims.Any(c => c.Type == "Language") ? User.Claims.First(c => c.Type == "Language").Value : "ur-PK",
RMuseumSecurableItem.ArtifactEntityShortName,
RMuseumSecurableItem.PublishOperationShortName
);
if (!string.IsNullOrEmpty(canPublish.ExceptionString))
return BadRequest(canPublish.ExceptionString);
RServiceResult itemInfo = await _artifactService.EditMasterRecord(item, canChangeStatusToAwaiting.Result, canPublish.Result);
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo == null)
{
return NotFound();
}
return Ok(); ;
}
///
/// Set Artifact Cover Item Index
///
///
///
///
[HttpPut("{id}/cover")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task SetArtifactCoverItemIndex(Guid id, [FromBody] int itemIndex)
{
RServiceResult res = await _artifactService.SetArtifactCoverItemIndex(id, itemIndex);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest();
return Ok();
}
///
/// get tag bundle by frindly url
///
///
///
[HttpGet("tagbundle/{friendlyUrl}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RTagBundleViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetTagBundleByFiendlyUrl(string friendlyUrl)
{
var cacheKey = $"tagbundle/{friendlyUrl}";
if (!_memoryCache.TryGetValue(cacheKey, out RServiceResult tag))
{
tag = await _artifactService.GetTagBundleByFiendlyUrl(friendlyUrl);
if (!string.IsNullOrEmpty(tag.ExceptionString))
{
return BadRequest(tag.ExceptionString);
}
if (tag.Result == null)
return NotFound();
_memoryCache.Set(cacheKey, tag, TimeSpan.FromHours(1));
}
RServiceResult lastModified = await _artifactService.GetMaxArtifactLastModified();
if (!string.IsNullOrEmpty(lastModified.ExceptionString))
{
return BadRequest(lastModified.ExceptionString);
}
DateTime lastModification = lastModified.Result;
Response.GetTypedHeaders().LastModified = TruncateToSeconds(lastModification);
Response.Headers.CacheControl = "public,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(lastModification))
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(tag.Result);
}
///
/// add new tag
///
/// only name is processed
///
[HttpPost("tag")]
[Authorize(Policy = RMuseumSecurableItem.TagEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RTag))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task NewTag([FromBody] RTag tag)
{
RServiceResult res = await _artifactService.AddTag(tag.Name);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// get all tags
///
///
///
[HttpGet("tag")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(IEnumerable))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetTags([FromQuery] PagingParameterModel paging)
{
RServiceResult<(PaginationMetadata PagingMeta, RTag[] Items)> itemsInfo = await _artifactService.GetAllTags(paging);
if (!string.IsNullOrEmpty(itemsInfo.ExceptionString))
{
return BadRequest(itemsInfo.ExceptionString);
}
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(itemsInfo.Result.PagingMeta));
return Ok(itemsInfo.Result.Items);
}
[HttpGet("tag/{friendlyUrl}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RTag))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetTagByFriendlyUrl(string friendlyUrl)
{
RServiceResult tag = await _artifactService.GetTagByFriendlyUrl(friendlyUrl);
if (!string.IsNullOrEmpty(tag.ExceptionString))
{
return BadRequest(tag.ExceptionString);
}
return Ok(tag.Result);
}
///
/// edit tag
///
///
/// editable fields are limited
///
///
///
///
[HttpPut("tag/{tagid}")]
[Authorize(Policy = RMuseumSecurableItem.TagEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task PutTag(Guid tagid, [FromBody] RTag tag)
{
if (tagid != tag.Id)
{
return BadRequest();
}
RServiceResult itemInfo = await _artifactService.EditTag(tag);
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo == null)
{
return NotFound();
}
return Ok(); ;
}
///
/// changes order of tags based on their position in artifacts
///
///
///
/// up / down
/// the other tag which its Order got replaced with the input id
[HttpPut("tag/move/{tagid}/in/{artifactId}/{upordown}")]
[Authorize(Policy = RMuseumSecurableItem.TagEntityShortName + ":" + RMuseumSecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(Guid))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task MoveTag(Guid tagId, Guid artifactId, string upordown)
{
RServiceResult otherTagId = await _artifactService.EditTagOrderBasedOnArtifact(tagId, artifactId, upordown == "up");
if (!string.IsNullOrEmpty(otherTagId.ExceptionString))
{
return BadRequest(otherTagId.ExceptionString);
}
return Ok((Guid)otherTagId.Result);
}
///
/// changes order of tags based on their position in artifact items
///
///
///
/// up / down
/// the other tag which its Order got replaced with the input id
[HttpPut("tag/move/{tagid}/in/item/{itemId}/{upordown}")]
[Authorize(Policy = RMuseumSecurableItem.TagEntityShortName + ":" + RMuseumSecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(Guid))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task MoveTagInItem(Guid tagId, Guid itemId, string upordown)
{
RServiceResult otherTagId = await _artifactService.EditTagOrderBasedOnItem(tagId, itemId, upordown == "up");
if (!string.IsNullOrEmpty(otherTagId.ExceptionString))
{
return BadRequest(otherTagId.ExceptionString);
}
return Ok((Guid)otherTagId.Result);
}
///
/// get tag value bundle by frindly url
///
///
///
///
[HttpGet("tagbundle/{friendlyUrl}/{valueUrl}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactTagViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetTagValueBundleByFiendlyUrl(string friendlyUrl, string valueUrl)
{
RServiceResult tag = await _artifactService.GetTagValueBundleByFiendlyUrl(friendlyUrl, valueUrl);
if (!string.IsNullOrEmpty(tag.ExceptionString))
{
return BadRequest(tag.ExceptionString);
}
if (tag.Result == null)
return NotFound();
return Ok(tag.Result);
}
///
/// get tag value by frindly url
///
///
///
///
[HttpGet("tagvalue/{tagId}/{friendlyUrl}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RTagValue))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetTagValueByFriendlyUrl(Guid tagId, string friendlyUrl)
{
RServiceResult tag = await _artifactService.GetTagValueByFriendlyUrl(tagId, friendlyUrl);
if (!string.IsNullOrEmpty(tag.ExceptionString))
{
return BadRequest(tag.ExceptionString);
}
return Ok(tag.Result);
}
///
/// add new tag value to artifact
///
///
/// only name is processed
///
[HttpPost("tagvalue/{artifactid}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.EditTagValueOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RTagValue))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task NewArtifactTagValue(Guid artifactId, [FromBody] RTag tag)
{
RServiceResult res = await _artifactService.TagArtifact(artifactId, tag);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// edit artifact attribute value
///
///
/// editable fields are limited
///
///
///
/// apply on all same value tags
///
[HttpPut("tagvalue/{artifactid}/{global=true}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.EditTagValueOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task PutAttributeValue(Guid artifactid, bool global, [FromBody] RTagValue tagvalue)
{
RServiceResult itemInfo = await _artifactService.EditTagValue(artifactid, tagvalue, global);
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo == null)
{
return NotFound();
}
return Ok(); ;
}
///
/// remove tag from artifact
///
///
///
///
[HttpDelete("tagvalue/{artifactId}/{tagValueId}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.EditTagValueOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(bool))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
public async Task RemoveArtifactTagValue(Guid artifactId, Guid tagValueId)
{
RServiceResult res = await _artifactService.UnTagArtifact(artifactId, tagValueId);
if (!string.IsNullOrEmpty(res.ExceptionString))
{
return BadRequest(res.ExceptionString);
}
return Ok(res.Result);
}
///
/// add new tag value to item
///
///
/// only tag.id is processed
///
[HttpPost("itemtagvalue/{itemId}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.EditTagValueOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RTagValue))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task NewItemTagValue(Guid itemId, [FromBody] RTag tag)
{
RServiceResult res = await _artifactService.TagItem(itemId, tag);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// edit item attribute value
///
///
/// editable fields are limited
///
///
///
/// apply on all same value tags
///
[HttpPut("itemtagvalue/{itemId}/{global=true}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.EditTagValueOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task PutItemTagValue(Guid itemId, bool global, [FromBody] RTagValue tagvalue)
{
RServiceResult itemInfo = await _artifactService.EditItemTagValue(itemId, tagvalue, global);
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo == null)
{
return NotFound();
}
return Ok(); ;
}
///
/// remove tag from item
///
///
///
///
[HttpDelete("itemtagvalue/{itemId}/{tagValueId}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.EditTagValueOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(bool))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
public async Task RemoveItemTagValue(Guid itemId, Guid tagValueId)
{
RServiceResult res = await _artifactService.UnTagItem(itemId, tagValueId);
if (!string.IsNullOrEmpty(res.ExceptionString))
{
return BadRequest(res.ExceptionString);
}
return Ok(res.Result);
}
///
/// changes order of tag values based on their position in an artifact
///
///
///
///
/// up / down
/// the other tag which its Order got replaced with the input id
[HttpPut("tagvalue/{artifactid}/{tagId}/{valueId}/move/{upordown}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.EditTagValueOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(Guid))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task MoveTagValue(Guid artifactId, Guid tagId, Guid valueId, string upordown)
{
RServiceResult otherValueId = await _artifactService.EditTagValueOrder(artifactId, tagId, valueId, upordown == "up");
if (!string.IsNullOrEmpty(otherValueId.ExceptionString))
{
return BadRequest(otherValueId.ExceptionString);
}
return Ok((Guid)otherValueId.Result);
}
///
/// changes order of tag values based on their position in an item
///
///
///
///
/// up / down
/// the other tag which its Order got replaced with the input id
[HttpPut("itemtagvalue/{itemId}/{tagId}/{valueId}/move/{upordown}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.EditTagValueOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(Guid))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task MoveItemTagValue(Guid itemId, Guid tagId, Guid valueId, string upordown)
{
RServiceResult otherValueId = await _artifactService.EditItemTagValueOrder(itemId, tagId, valueId, upordown == "up");
if (!string.IsNullOrEmpty(otherValueId.ExceptionString))
{
return BadRequest(otherValueId.ExceptionString);
}
return Ok((Guid)otherValueId.Result);
}
///
/// update an artifact item info
///
///
///
[HttpPut("item")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task UpdateArtifactItemRecordAsync([FromBody]RArtifactItemRecord item)
{
var res = await _artifactService.UpdateArtifactItemRecordAsync(item);
if(!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok();
}
///
/// gets specified publish artifact item info (including images + attributes)
///
///
///
///
[HttpGet("secure/{artifactUrl}/{itemUrl}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactItemRecordViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task GetArtifactItemByFrienlyUrlUserVisible(string artifactUrl, string itemUrl)
{
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 itemInfo = await _artifactService.GetArtifactItemByFrienlyUrl(artifactUrl, itemUrl, visibleItems);
if (!string.IsNullOrEmpty(itemInfo.ExceptionString))
{
return BadRequest(itemInfo.ExceptionString);
}
if (itemInfo.Result == null)
return NotFound();
Response.GetTypedHeaders().LastModified = TruncateToSeconds(itemInfo.Result.Item.LastModified);
Response.Headers.CacheControl = "private,max-age=300";
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= TruncateToSeconds(itemInfo.Result.Item.LastModified))
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(itemInfo.Result);
}
///
/// Add new artifact (multipart/form-data)
///
///
/// const data = new FormData();
/// data.append('name', 'تست');
/// data.append('description', '');
/// data.append('srcUrl', '');
/// data.append('picTitle', 'تست');
/// data.append('picDescription', '');
/// data.append('file', this.file);
/// data.append('picSrcUrl', '');
///
///
///
///
[HttpPost]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + SecurableItem.AddOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactMasterRecord))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public virtual async Task Post()
{
try
{
NewArtifact newArtifactInfo =
new NewArtifact()
{
Name = Request.Form["name"],
Description = Request.Form["description"],
SrcUrl = Request.Form["srcUrl"],
PicTitle = Request.Form["picTitle"],
PicDescription = Request.Form["picDescription"],
File = Request.Form.Files[0],
PicSrcUrl = Request.Form["picSrcUrl"]
};
RServiceResult result =
await _artifactService.Add
(
newArtifactInfo.Name, newArtifactInfo.Description, newArtifactInfo.SrcUrl,
newArtifactInfo.PicTitle, newArtifactInfo.PicDescription, newArtifactInfo.File,
newArtifactInfo.PicSrcUrl,
null);
if (result.Result == null)
return BadRequest(result.ExceptionString);
return Ok(result.Result);
}
catch (Exception exp)
{
return BadRequest(exp.ToString());
}
}
///
/// import from external resources
///
/// pdf/loc/princeton/harvard/qajarwomen/hathitrust/penn/cam/bl/folder/walters/cbl/append/iiif
/// 119/foldername
/// golestan-baysonghori/artifact id
///
///
///
[HttpPost]
[Route("import")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ImportOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(bool))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task Import(string srcType, string resourceNumber, string friendlyUrl, string resourcePrefix, bool skipUpload)
{
RServiceResult res =
await _artifactService.Import(srcType, resourceNumber, friendlyUrl, resourcePrefix, skipUpload);
if (res.Result)
return Ok();
return BadRequest(res.ExceptionString);
}
///
/// keep alive (for import background service)
///
/// true
[HttpGet]
[Route("keep-alive")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(bool))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public IActionResult KeepAlive()
{
return Ok(true);
}
///
/// retry import
///
///
[HttpPost]
[Route("retryimport")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ImportOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task RetryImport(JobType jobType = JobType.BritishLibrary, bool skipUpload = false)
{
RServiceResult res = await _artifactService.RescheduleJobs(jobType, skipUpload);
if (res.Result)
return Ok();
return BadRequest(res.ExceptionString);
}
///
/// due to a bug in loc json outputs some artifacts with more than 1000 pages were downloaded incompletely
///
/// 123456
///
///
[HttpPost]
[Route("reexamineimport")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ImportOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(string[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task ReExamineLocDownloads(string pass, bool skipUpload)
{
if (pass != "123456") //this is a heavy processor consuming call, so prevent mistaken call of it from swagger ui
return BadRequest("invalid password");
RServiceResult res = await _artifactService.ReExamineLocDownloads(skipUpload);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
[HttpGet]
[Route("jobs")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + SecurableItem.AddOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(IEnumerable))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetImportJobs([FromQuery] PagingParameterModel paging)
{
RServiceResult<(PaginationMetadata PagingMeta, ImportJob[] Items)> itemsInfo = await _artifactService.GetImportJobs(paging);
if (!string.IsNullOrEmpty(itemsInfo.ExceptionString))
{
return BadRequest(itemsInfo.ExceptionString);
}
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(itemsInfo.Result.PagingMeta));
return Ok(itemsInfo.Result.Items);
}
///
/// bookmark artifact
///
///
///
[HttpPost]
[Route("bookmark/{artifactId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserBookmark))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task BookmarkArtifact(Guid artifactId)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.BookmarkArtifact(artifactId, loggedOnUserId, RBookmarkType.Bookmark);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// bookmark item
///
///
///
[HttpPost]
[Route("bookmark/item/{itemId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserBookmark))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task BookmarkItem(Guid itemId)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.BookmarkItem(itemId, loggedOnUserId, RBookmarkType.Bookmark);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// item bookmarks info
///
///
///
[HttpDelete]
[Route("bookmark/{bookmarkId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task DeleteBookmark(Guid bookmarkId)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.DeleteUserBookmark(bookmarkId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok();
}
///
/// fav artifact
///
///
///
[HttpPost]
[Route("fav/{artifactId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserBookmark))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task FavArtifact(Guid artifactId)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.BookmarkArtifact(artifactId, loggedOnUserId, RBookmarkType.Favorite);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// fav item
///
///
///
[HttpPost]
[Route("fav/item/{itemId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserBookmark))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task FavItem(Guid itemId)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.BookmarkItem(itemId, loggedOnUserId, RBookmarkType.Favorite);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// artifact bookmarks info
///
///
///
[HttpGet]
[Route("bookmark/{artifactId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserBookmark[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetArtifactUserBookmarks(Guid artifactId)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.GetArtifactUserBookmarks(artifactId, loggedOnUserId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// item bookmarks info
///
///
///
[HttpGet]
[Route("bookmark/item/{itemId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserBookmark[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GeItemUserBookmarks(Guid itemId)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.GeItemUserBookmarks(itemId, loggedOnUserId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// user bookmarks
///
///
[HttpGet]
[Route("bookmark")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserBookmark[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetUserBookmarks([FromQuery] PagingParameterModel paging)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult v = await _GetUserVisibleArtifactStatusSet
(
loggedOnUserId,
new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value)
);
if (!string.IsNullOrEmpty(v.ExceptionString))
return BadRequest(v.ExceptionString);
PublishStatus[] visibleItems = v.Result;
RServiceResult<(PaginationMetadata PagingMeta, RUserBookmarkViewModel[] Bookmarks)> res = await _artifactService.GetBookmarks(paging, loggedOnUserId, RBookmarkType.Bookmark, visibleItems);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(res.Result.PagingMeta));
return Ok(res.Result.Bookmarks);
}
///
/// user favorites
///
///
[HttpGet]
[Route("fav")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserBookmarkViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetUserFavorites([FromQuery] PagingParameterModel paging)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult v = await _GetUserVisibleArtifactStatusSet
(
loggedOnUserId,
new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value)
);
if (!string.IsNullOrEmpty(v.ExceptionString))
return BadRequest(v.ExceptionString);
PublishStatus[] visibleItems = v.Result;
RServiceResult<(PaginationMetadata PagingMeta, RUserBookmarkViewModel[] Bookmarks)> res = await _artifactService.GetBookmarks(paging, loggedOnUserId, RBookmarkType.Favorite, visibleItems);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(res.Result.PagingMeta));
return Ok(res.Result.Bookmarks);
}
///
/// add note for artifact
///
///
///
[HttpPost]
[Route("note")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserNoteViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task AddUserNoteToArtifact([FromBody] PostUserNote note)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.AddUserNoteToArtifact(note.EntityId, loggedOnUserId, note.NoteType, note.Contents, note.ReferenceNoteId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// add note for artifact item
///
///
///
[HttpPost]
[Route("note/item")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserNoteViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task AddUserNoteToArtifactItem([FromBody] PostUserNote note)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.AddUserNoteToArtifactItem(note.EntityId, loggedOnUserId, note.NoteType, note.Contents, note.ReferenceNoteId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// Edit User Notes
///
/// a note can not be edited by a user other than its owner or another using having note:moderate permission
///
/// only htmlContent is processed
///
[HttpPut]
[Route("note/{noteId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserNoteViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task EditUserNote(Guid noteId, [FromBody] PostUserNote note)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult
canModerate =
await _userPermissionChecker.Check
(
loggedOnUserId,
new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value),
User.Claims.Any(c => c.Type == "Language") ? User.Claims.First(c => c.Type == "Language").Value : "ur-PK",
RMuseumSecurableItem.NoteEntityShortName,
RMuseumSecurableItem.ModerateOperationShortName
);
if (!string.IsNullOrEmpty(canModerate.ExceptionString))
return BadRequest(canModerate.ExceptionString);
RServiceResult res = await _artifactService.EditUserNote(noteId, canModerate.Result ? (Guid?)null : loggedOnUserId, note.Contents);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// delete user notes
///
///
/// 1. a note can not be deleted by a user other than its owner or another using having note:moderate permission
/// 2. all notes which have refernce to deleting note (sent in reply to it) would be deleted irrelevant of their ownership
///
///
/// list of notes deleted
[HttpDelete]
[Route("note/{noteId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(Guid[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task DeleteUserNote(Guid noteId)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult
canModerate =
await _userPermissionChecker.Check
(
loggedOnUserId,
new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value),
User.Claims.Any(c => c.Type == "Language") ? User.Claims.First(c => c.Type == "Language").Value : "ur-PK",
RMuseumSecurableItem.NoteEntityShortName,
RMuseumSecurableItem.ModerateOperationShortName
);
if (!string.IsNullOrEmpty(canModerate.ExceptionString))
return BadRequest(canModerate.ExceptionString);
RServiceResult res = await _artifactService.DeleteUserNote(noteId, canModerate.Result ? (Guid?)null : loggedOnUserId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// get private notes for artifact
///
///
///
[HttpGet]
[Route("note/private/{artifactId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserNoteViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetArtifactUserNotes(Guid artifactId)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.GetArtifactUserNotes(artifactId, loggedOnUserId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// get private notes for artifact
///
///
///
[HttpGet]
[Route("note/{artifactId}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserNoteViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetArtifactPublicNotes(Guid artifactId)
{
RServiceResult res = await _artifactService.GetArtifactPublicNotes(artifactId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// get private notes for artifact item
///
///
///
[HttpGet]
[Route("note/item/private/{itemId}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserNoteViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetArtifactItemUserNotes(Guid itemId)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.GetArtifactItemUserNotes(itemId, loggedOnUserId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// get public notes for artifact item
///
///
///
[HttpGet]
[Route("note/item/{itemId}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserNoteViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetArtifactItemPublicNotes(Guid itemId)
{
RServiceResult res = await _artifactService.GetArtifactItemPublicNotes(itemId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// user public notes
///
///
[HttpGet]
[Route("note/public")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserNoteViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetUserPublicNotes([FromQuery] PagingParameterModel paging)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult v = await _GetUserVisibleArtifactStatusSet
(
loggedOnUserId,
new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value)
);
if (!string.IsNullOrEmpty(v.ExceptionString))
return BadRequest(v.ExceptionString);
PublishStatus[] visibleItems = v.Result;
RServiceResult<(PaginationMetadata PagingMeta, RUserNoteViewModel[] Notes)> res = await _artifactService.GetUserNotes(loggedOnUserId, paging, RNoteType.Public, visibleItems);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(res.Result.PagingMeta));
return Ok(res.Result.Notes);
}
///
/// user public notes
///
///
[HttpGet]
[Route("note/private")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserNoteViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetUserPrivateNotes([FromQuery] PagingParameterModel paging)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult v = await _GetUserVisibleArtifactStatusSet
(
loggedOnUserId,
new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value)
);
if (!string.IsNullOrEmpty(v.ExceptionString))
return BadRequest(v.ExceptionString);
PublishStatus[] visibleItems = v.Result;
RServiceResult<(PaginationMetadata PagingMeta, RUserNoteViewModel[] Notes)> res = await _artifactService.GetUserNotes(loggedOnUserId, paging, RNoteType.Private, visibleItems);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(res.Result.PagingMeta));
return Ok(res.Result.Notes);
}
///
/// all users public notes
///
///
[HttpGet]
[Route("note/all")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RUserNoteViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetAllPublicNotes([FromQuery] PagingParameterModel paging)
{
RServiceResult<(PaginationMetadata PagingMeta, RUserNoteViewModel[] Notes)> res = await _artifactService.GetAllPublicNotes(paging);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(res.Result.PagingMeta));
return Ok(res.Result.Notes);
}
///
/// report a public note
///
///
/// id of saved report
[HttpPost]
[Route("note/report")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(Guid))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
public async Task ReportPublicNote([FromBody] PostRUserNoteAbuseReportViewModel report)
{
if (ReadOnlyMode)
return BadRequest("سایت به دلایل فنی مثل انتقال سرور موقتاً در حالت فقط خواندنی قرار دارد. لطفاً ساعاتی دیگر مجدداً تلاش کنید.");
Guid userId =
new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
Guid sessionId =
new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value);
RServiceResult sessionCheckResult = await _appUserService.SessionExists(userId, sessionId);
if (!string.IsNullOrEmpty(sessionCheckResult.ExceptionString))
{
return StatusCode((int)HttpStatusCode.Forbidden);
}
RServiceResult res = await _artifactService.ReportPublicNote(userId, report.NoteId, report.ReasonText);
if (!string.IsNullOrEmpty(res.ExceptionString))
{
return BadRequest(res.ExceptionString);
}
return Ok(res.Result);
}
///
/// Get a list of reported notes
///
///
///
[HttpGet]
[Route("notes/reported")]
[Authorize(Policy = RMuseumSecurableItem.NoteEntityShortName + ":" + RMuseumSecurableItem.ModerateOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(IEnumerable))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetReportedPublicNotes([FromQuery] PagingParameterModel paging)
{
var notes = await _artifactService.GetReportedPublicNotes(paging);
if (!string.IsNullOrEmpty(notes.ExceptionString))
{
return BadRequest(notes.ExceptionString);
}
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(notes.Result.PagingMeta));
return Ok(notes.Result.Items);
}
///
/// delete a report for abuse in public user notes
///
///
///
[HttpDelete]
[Route("note/report/{id}")]
[Authorize(Policy = RMuseumSecurableItem.NoteEntityShortName + ":" + RMuseumSecurableItem.ModerateOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(int))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
public async Task DeclinePublicNoteReport(Guid id)
{
if (ReadOnlyMode)
return BadRequest("سایت به دلایل فنی مثل انتقال سرور موقتاً در حالت فقط خواندنی قرار دارد. لطفاً ساعاتی دیگر مجدداً تلاش کنید.");
RServiceResult res = await _artifactService.DeclinePublicNoteReport(id);
if (!string.IsNullOrEmpty(res.ExceptionString))
{
return BadRequest(res.ExceptionString);
}
if (!res.Result)
{
return NotFound();
}
return Ok();
}
///
/// delete a reported user note (accept the complaint)
///
///
///
[HttpDelete]
[Route("note/reported/moderate/{reportid}")]
[Authorize(Policy = RMuseumSecurableItem.NoteEntityShortName + ":" + RMuseumSecurableItem.ModerateOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
public async Task AcceptPublicNoteReport(Guid reportid)
{
if (ReadOnlyMode)
return BadRequest("سایت به دلایل فنی مثل انتقال سرور موقتاً در حالت فقط خواندنی قرار دارد. لطفاً ساعاتی دیگر مجدداً تلاش کنید.");
var res =
await _artifactService.AcceptPublicNoteReport(reportid);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
if (!res.Result)
return NotFound();
return Ok();
}
///
/// suggest divan link
///
///
///
[HttpPost]
[Route("divan")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(DivanLinkViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task SuggestDivanLink([FromBody] LinkSuggestion link)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult suggestion = await _artifactService.SuggestDivanLink(loggedOnUserId, link);
if (!string.IsNullOrEmpty(suggestion.ExceptionString))
return BadRequest(suggestion.ExceptionString);
return Ok(suggestion.Result);
}
///
/// get suggested divan links
///
///
///
///
[HttpGet]
[Route("divan")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(DivanLinkViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetSuggestedLinks(ReviewResult status, bool notSynced)
{
RServiceResult res = await _artifactService.GetSuggestedLinks(status, notSynced);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// finds next unsynchronized suggested link with an aleady synched one from the artificat if exists,
/// return value might be null or an array with length 1 or 2 (has paging-headers)
///
/// has paging-headers
///
/// return value might be null or an array with length 1 or 2
[HttpGet]
[Route("divan/nextunsychedimage")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(DivanLinkViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetNextUnsynchronizedSuggestedLinkWithAlreadySynchedOneForPoem(int skip)
{
RServiceResult res = await _artifactService.GetNextUnsynchronizedSuggestedLinkWithAlreadySynchedOneForPoem(skip);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
var resCount = await _artifactService.GetUnsynchronizedSuggestedLinksCount();
if (!string.IsNullOrEmpty(resCount.ExceptionString))
return BadRequest(resCount.ExceptionString);
// Paging Header
HttpContext.Response.Headers.Append("paging-headers",
JsonConvert.SerializeObject(
new PaginationMetadata()
{
totalCount = resCount.Result,
pageSize = -1,
currentPage = -1,
hasNextPage = false,
hasPreviousPage = false,
totalPages = -1
})
);
return Ok(res.Result);
}
///
/// review suggested divan link
///
///
///
///
[HttpPut]
[Route("divan/review/{linkId}/{result}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ReviewDivanLinksOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task ReviewDivanLink(Guid linkId, ReviewResult result)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult suggestion = await _artifactService.ReviewSuggestedLink(linkId, loggedOnUserId, result);
if (!string.IsNullOrEmpty(suggestion.ExceptionString))
return BadRequest(suggestion.ExceptionString);
return Ok();
}
///
/// mark suggested divan link as synchronized
///
///
/// display ogn page
///
[HttpPut]
[Route("divan/sync/{linkId}/{displayOnPage}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ReviewDivanLinksOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task SynchronizeDivanLink(Guid linkId, bool displayOnPage)
{
RServiceResult suggestion = await _artifactService.SynchronizeSuggestedLink(linkId, displayOnPage);
if (!string.IsNullOrEmpty(suggestion.ExceptionString))
return BadRequest(suggestion.ExceptionString);
return Ok();
}
///
/// remove divan link
///
///
///
///
[HttpDelete]
[Route("divan")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ReviewDivanLinksOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task RemoveDivanLinkAsync(Guid linkId, bool removeItemLink)
{
RServiceResult suggestion = await _artifactService.RemoveDivanLinkAsync(linkId, removeItemLink);
if (!string.IsNullOrEmpty(suggestion.ExceptionString))
return BadRequest(suggestion.ExceptionString);
return Ok();
}
///
///toc / temporary one time api / to be removed
///
///
[HttpPut]
[Route("divan/toc")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ReviewDivanLinksOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task AddTOCForSuggestedLinks()
{
RServiceResult suggestion = await _artifactService.AddTOCForSuggestedLinks();
if (!string.IsNullOrEmpty(suggestion.ExceptionString))
return BadRequest(suggestion.ExceptionString);
return Ok(suggestion.Result);
}
///
/// get suggested pinterest links
///
///
///
///
[HttpGet]
[Route("pinterest")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(PinterestLinkViewModel[]))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task GetSuggestedPinterestLinks(ReviewResult status, bool notSynced)
{
RServiceResult res = await _artifactService.GetSuggestedPinterestLinks(status, notSynced);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// suggest pinterest link for divan
///
///
///
[HttpPost]
[Route("pinterest")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(PinterestLinkViewModel))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task SuggestPinterestLink([FromBody] PinterestSuggestion suggestion)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult res = await _artifactService.SuggestPinterestLink(loggedOnUserId, suggestion);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// review suggested divan pinterest link
///
///
///
///
///
///
///
[HttpPut]
[Route("pinterest/review/{linkId}/{result}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ReviewDivanLinksOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task ReviewSuggestedPinterestLink(Guid linkId, string altText, ReviewResult result, string reviewDesc, string imageUrl)
{
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
RServiceResult suggestion = await _artifactService.ReviewSuggestedPinterestLink(linkId, loggedOnUserId, altText, result, reviewDesc, imageUrl);
if (!string.IsNullOrEmpty(suggestion.ExceptionString))
return BadRequest(suggestion.ExceptionString);
return Ok();
}
///
/// mark suggested pinterest divan link as synchronized
///
///
///
[HttpPut]
[Route("pinterest/sync/{linkId}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ReviewDivanLinksOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task SynchronizeSuggestedPinterestLink(Guid linkId)
{
RServiceResult suggestion = await _artifactService.SynchronizeSuggestedPinterestLink(linkId);
if (!string.IsNullOrEmpty(suggestion.ExceptionString))
return BadRequest(suggestion.ExceptionString);
return Ok();
}
///
/// remove pinterest link
///
///
///
[HttpDelete]
[Route("pinterest")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ReviewDivanLinksOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task RemovePinterestLinkAsync(Guid linkId)
{
RServiceResult suggestion = await _artifactService.RemovePinterestLinkAsync(linkId);
if (!string.IsNullOrEmpty(suggestion.ExceptionString))
return BadRequest(suggestion.ExceptionString);
return Ok();
}
///
/// start filling DivanLink table OriginalSource values
///
///
[HttpPut("divanlink/fillsource")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ReviewDivanLinksOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
public IActionResult StartFillingDivanLinkOriginalSources()
{
try
{
var res = _artifactService.StartFillingDivanLinkOriginalSources();
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok();
}
catch (Exception exp)
{
return BadRequest(exp.ToString());
}
}
///
/// start removing original images
///
///
[HttpDelete("originalimages/remove")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ImportOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
public IActionResult StartRemovingOriginalImages()
{
try
{
var res = _artifactService.StartRemovingOriginalImages();
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok();
}
catch (Exception exp)
{
return BadRequest(exp.ToString());
}
}
///
/// search artifacts
///
///
///
///
[HttpGet]
[Route("search")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(IEnumerable))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task SearchArtifacts([FromQuery] PagingParameterModel paging, string term)
{
var pagedResult = await _artifactService.SearchArtifacts(paging, term);
if (!string.IsNullOrEmpty(pagedResult.ExceptionString))
return BadRequest(pagedResult.ExceptionString);
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(pagedResult.Result.PagingMeta));
return Ok(pagedResult.Result.Items);
}
///
/// search artifact items
///
///
///
///
[HttpGet]
[Route("search/items")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(IEnumerable))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task SearchArtifactItems([FromQuery] PagingParameterModel paging, string term)
{
var pagedResult = await _artifactService.SearchArtifactItems(paging, term);
if (!string.IsNullOrEmpty(pagedResult.ExceptionString))
return BadRequest(pagedResult.ExceptionString);
// Paging Header
HttpContext.Response.Headers.Append("paging-headers", JsonConvert.SerializeObject(pagedResult.Result.PagingMeta));
return Ok(pagedResult.Result.Items);
}
///
/// start setting an artifact items as a category poems text original source
///
///
///
///
[HttpPut("divanlink/settextorigin/{divanCatId}/{artifactId}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + RMuseumSecurableItem.ReviewDivanLinksOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
public IActionResult StartSettingArtifactAsTextOriginalSource(int divanCatId, Guid artifactId)
{
try
{
var res = _artifactService.StartSettingArtifactAsTextOriginalSource(divanCatId, artifactId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok();
}
catch (Exception exp)
{
return BadRequest(exp.ToString());
}
}
///
/// upload artifact to external server
///
///
///
///
[HttpPut("upload/external/{friendlyUrl}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
public IActionResult StartUploadingArtifactToExternalServer(string friendlyUrl, bool skipUpload)
{
try
{
var res = _artifactService.StartUploadingArtifactToExternalServer(friendlyUrl, skipUpload);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok();
}
catch (Exception exp)
{
return BadRequest(exp.ToString());
}
}
///
/// create images for divan
///
///
///
[HttpPut("ai/create/images")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
public async Task OpenAIStartCreatingImagesForPoemsAsync(int startPoetId = 0)
{
try
{
await _artifactService.OpenAIStartCreatingImagesForPoemsAsync(startPoetId);
return Ok();
}
catch (Exception exp)
{
return BadRequest(exp.ToString());
}
}
///
/// create images for divan - offline
///
///
[HttpPut("ai/create/images/offline")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
public async Task OpenAIStartCreatingImagesForPoemsOfflineAsync()
{
try
{
await _artifactService.OpenAIStartCreatingImagesForPoemsOfflineAsync();
return Ok();
}
catch (Exception exp)
{
return BadRequest(exp.ToString());
}
}
///
/// add a new item to an artifact
///
///
///
///
[HttpPut("item/{artifactFriendlyUrl}")]
[Authorize(Policy = RMuseumSecurableItem.ArtifactEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(RArtifactItemRecord))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
public async Task AddItemToArtifactAsync(string artifactFriendlyUrl, IFormFile jpeg)
{
var res = await _artifactService.AddItemToArtifactAsync(artifactFriendlyUrl, jpeg, null);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
///
/// readonly mode
///
public bool ReadOnlyMode
{
get
{
try
{
return bool.Parse(Configuration["ReadOnlyMode"]);
}
catch
{
return false;
}
}
}
///
/// constructor
///
///
///
///
///
///
///
public ArtifactController(IArtifactService artifactService, IUserPermissionChecker userPermissionChecker, IMemoryCache memoryCache, ICaptchaService captchaService, IAppUserService appUserService, IConfiguration configuration)
{
_artifactService = artifactService;
_userPermissionChecker = userPermissionChecker;
_memoryCache = memoryCache;
_captchaService = captchaService;
_appUserService = appUserService;
Configuration = configuration;
}
///
/// Artifact Service
///
protected readonly IArtifactService _artifactService;
///
/// IUserPermissionChecker instance
///
protected IUserPermissionChecker _userPermissionChecker;
///
/// IMemoryCache
///
protected readonly IMemoryCache _memoryCache;
///
/// Captcha service
///
protected readonly ICaptchaService _captchaService;
///
/// IAppUserService instance
///
protected IAppUserService _appUserService;
///
/// Configuration
///
protected IConfiguration Configuration { get; }
}
}