using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Timeline.Entities;
using Timeline.Models;
using Timeline.Models.Http;
using Timeline.Models.Validation;
using Timeline.Services;
using Timeline.Services.Mapper;
using Timeline.Services.Timeline;
using Timeline.Services.User;
namespace Timeline.Controllers
{
///
/// Operations about timeline.
///
[ApiController]
[Route("timelines")]
[ProducesErrorResponseType(typeof(CommonResponse))]
public class TimelineController : Controller
{
private readonly IUserService _userService;
private readonly ITimelineService _service;
private readonly IGenericMapper _mapper;
public TimelineController(IUserService userService, ITimelineService service, IGenericMapper mapper)
{
_userService = userService;
_service = service;
_mapper = mapper;
}
private bool UserHasAllTimelineManagementPermission => this.UserHasPermission(UserPermission.AllTimelineManagement);
private Task Map(TimelineEntity timeline)
{
return _mapper.MapAsync(timeline, Url, User);
}
private Task> Map(List timelines)
{
return _mapper.MapListAsync(timelines, Url, User);
}
///
/// List all timelines.
///
/// A username. If set, only timelines related to the user will return.
/// Specify the relation type, may be 'own' or 'join'. If not set, both type will return.
/// "Private" or "Register" or "Public". If set, only timelines whose visibility is specified one will return.
/// The timeline list.
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task>> TimelineList([FromQuery][Username] string? relate, [FromQuery][ValidationSet("own", "join", "default")] string? relateType, [FromQuery] string? visibility)
{
List? visibilityFilter = null;
if (visibility != null)
{
visibilityFilter = new List();
var items = visibility.Split('|');
foreach (var item in items)
{
if (item.Equals(nameof(TimelineVisibility.Private), StringComparison.OrdinalIgnoreCase))
{
if (!visibilityFilter.Contains(TimelineVisibility.Private))
visibilityFilter.Add(TimelineVisibility.Private);
}
else if (item.Equals(nameof(TimelineVisibility.Register), StringComparison.OrdinalIgnoreCase))
{
if (!visibilityFilter.Contains(TimelineVisibility.Register))
visibilityFilter.Add(TimelineVisibility.Register);
}
else if (item.Equals(nameof(TimelineVisibility.Public), StringComparison.OrdinalIgnoreCase))
{
if (!visibilityFilter.Contains(TimelineVisibility.Public))
visibilityFilter.Add(TimelineVisibility.Public);
}
else
{
return BadRequest(ErrorResponse.Common.CustomMessage_InvalidModel(Resources.Messages.TimelineController_QueryVisibilityUnknown, item));
}
}
}
TimelineUserRelationship? relationship = null;
if (relate != null)
{
try
{
var relatedUserId = await _userService.GetUserIdByUsernameAsync(relate);
var relationType = relateType is null ? TimelineUserRelationshipType.Default : Enum.Parse(relateType, true);
relationship = new TimelineUserRelationship(relationType, relatedUserId);
}
catch (EntityNotExistException)
{
return BadRequest(ErrorResponse.TimelineController.QueryRelateNotExist());
}
}
var timelines = await _service.GetTimelinesAsync(relationship, visibilityFilter);
var result = await Map(timelines);
return result;
}
///
/// Get info of a timeline.
///
/// The timeline name.
/// The timeline info.
[HttpGet("{timeline}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task> TimelineGet([FromRoute][GeneralTimelineName] string timeline)
{
var timelineId = await _service.GetTimelineIdByNameAsync(timeline);
var t = await _service.GetTimelineAsync(timelineId);
var result = await Map(t);
return result;
}
///
/// Change properties of a timeline.
///
/// Timeline name.
///
/// The new info.
[HttpPatch("{timeline}")]
[Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task> TimelinePatch([FromRoute][GeneralTimelineName] string timeline, [FromBody] HttpTimelinePatchRequest body)
{
var timelineId = await _service.GetTimelineIdByNameAsync(timeline);
if (!UserHasAllTimelineManagementPermission && !await _service.HasManagePermissionAsync(timelineId, this.GetUserId()))
{
return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
}
await _service.ChangePropertyAsync(timelineId, _mapper.AutoMapperMap(body));
var t = await _service.GetTimelineAsync(timelineId);
var result = await Map(t);
return result;
}
///
/// Add a member to timeline.
///
/// Timeline name.
/// The new member's username.
[HttpPut("{timeline}/members/{member}")]
[Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task> TimelineMemberPut([FromRoute][GeneralTimelineName] string timeline, [FromRoute][Username] string member)
{
var timelineId = await _service.GetTimelineIdByNameAsync(timeline);
if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermissionAsync(timelineId, this.GetUserId())))
{
return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
}
var userId = await _userService.GetUserIdByUsernameAsync(member);
var create = await _service.AddMemberAsync(timelineId, userId);
return Ok(CommonPutResponse.Create(create));
}
///
/// Remove a member from timeline.
///
/// Timeline name.
/// The member's username.
[HttpDelete("{timeline}/members/{member}")]
[Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task TimelineMemberDelete([FromRoute][GeneralTimelineName] string timeline, [FromRoute][Username] string member)
{
var timelineId = await _service.GetTimelineIdByNameAsync(timeline);
if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermissionAsync(timelineId, this.GetUserId())))
{
return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
}
var userId = await _userService.GetUserIdByUsernameAsync(member);
var delete = await _service.RemoveMemberAsync(timelineId, userId);
return Ok(CommonDeleteResponse.Create(delete));
}
///
/// Create a timeline.
///
///
/// Info of new timeline.
[HttpPost]
[Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task> TimelineCreate([FromBody] HttpTimelineCreateRequest body)
{
var userId = this.GetUserId();
var timeline = await _service.CreateTimelineAsync(body.Name, userId);
var result = await Map(timeline);
return result;
}
///
/// Delete a timeline.
///
/// Timeline name.
/// Info of deletion.
[HttpDelete("{timeline}")]
[Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task TimelineDelete([FromRoute][TimelineName] string timeline)
{
var timelineId = await _service.GetTimelineIdByNameAsync(timeline);
if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermissionAsync(timelineId, this.GetUserId())))
{
return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
}
await _service.DeleteTimelineAsync(timelineId);
return Ok();
}
}
}