aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BackEnd/Timeline/Controllers/TimelinePostController.cs4
-rw-r--r--BackEnd/Timeline/Models/Validation/Validator.cs2
-rw-r--r--BackEnd/Timeline/Services/TimelinePostService.cs122
3 files changed, 71 insertions, 57 deletions
diff --git a/BackEnd/Timeline/Controllers/TimelinePostController.cs b/BackEnd/Timeline/Controllers/TimelinePostController.cs
index afe9b36f..6b7ba411 100644
--- a/BackEnd/Timeline/Controllers/TimelinePostController.cs
+++ b/BackEnd/Timeline/Controllers/TimelinePostController.cs
@@ -142,7 +142,7 @@ namespace Timeline.Controllers
{
return BadRequest(ErrorResponse.Common.CustomMessage_InvalidModel(Resources.Messages.TimelineController_TextContentTextRequired));
}
- post = await _postService.CreateTextPost(timelineId, userId, text, body.Time);
+ post = await _postService.CreateTextPost(timelineId, userId, text, new TimelinePostCommonProperties { Time = body.Time });
}
else if (content.Type == TimelinePostContentTypes.Image)
{
@@ -163,7 +163,7 @@ namespace Timeline.Controllers
try
{
- post = await _postService.CreateImagePost(timelineId, userId, data, body.Time);
+ post = await _postService.CreateImagePost(timelineId, userId, data, new TimelinePostCommonProperties { Time = body.Time });
}
catch (ImageException)
{
diff --git a/BackEnd/Timeline/Models/Validation/Validator.cs b/BackEnd/Timeline/Models/Validation/Validator.cs
index b7e754d3..ec6cc0af 100644
--- a/BackEnd/Timeline/Models/Validation/Validator.cs
+++ b/BackEnd/Timeline/Models/Validation/Validator.cs
@@ -51,7 +51,7 @@ namespace Timeline.Models.Validation
public (bool, string) Validate(object? value)
{
- if (value == null)
+ if (value is null)
{
if (PermitNull)
return (true, GetSuccessMessage());
diff --git a/BackEnd/Timeline/Services/TimelinePostService.cs b/BackEnd/Timeline/Services/TimelinePostService.cs
index a8bdbf92..c2b773ff 100644
--- a/BackEnd/Timeline/Services/TimelinePostService.cs
+++ b/BackEnd/Timeline/Services/TimelinePostService.cs
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Timeline.Entities;
using Timeline.Helpers;
using Timeline.Models;
+using Timeline.Models.Validation;
using Timeline.Services.Exceptions;
using static Timeline.Resources.Services.TimelineService;
@@ -23,6 +24,14 @@ namespace Timeline.Services
public DateTime? LastModified { get; set; } // TODO: Why nullable?
}
+ public class TimelinePostCommonProperties
+ {
+ public string? Color { get; set; }
+
+ /// <summary>If not set, current time is used.</summary>
+ public DateTime? Time { get; set; }
+ }
+
public interface ITimelinePostService
{
/// <summary>
@@ -64,12 +73,12 @@ namespace Timeline.Services
/// <param name="timelineId">The id of the timeline to create post against.</param>
/// <param name="authorId">The author's user id.</param>
/// <param name="text">The content text.</param>
- /// <param name="time">The time of the post. If null, then current time is used.</param>
+ /// <param name="properties">Some properties.</param>
/// <returns>The info of the created post.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="text"/> is null.</exception>
/// <exception cref="TimelineNotExistException">Thrown when timeline does not exist.</exception>
/// <exception cref="UserNotExistException">Thrown if user of <paramref name="authorId"/> does not exist.</exception>
- Task<TimelinePostEntity> CreateTextPost(long timelineId, long authorId, string text, DateTime? time);
+ Task<TimelinePostEntity> CreateTextPost(long timelineId, long authorId, string text, TimelinePostCommonProperties? properties = null);
/// <summary>
/// Create a new image post in timeline.
@@ -77,13 +86,13 @@ namespace Timeline.Services
/// <param name="timelineId">The id of the timeline to create post against.</param>
/// <param name="authorId">The author's user id.</param>
/// <param name="imageData">The image data.</param>
- /// <param name="time">The time of the post. If null, then use current time.</param>
+ /// <param name="properties">Some properties.</param>
/// <returns>The info of the created post.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="imageData"/> is null.</exception>
/// <exception cref="TimelineNotExistException">Thrown when timeline does not exist.</exception>
/// <exception cref="UserNotExistException">Thrown if user of <paramref name="authorId"/> does not exist.</exception>
/// <exception cref="ImageException">Thrown if data is not a image. Validated by <see cref="ImageValidator"/>.</exception>
- Task<TimelinePostEntity> CreateImagePost(long timelineId, long authorId, byte[] imageData, DateTime? time);
+ Task<TimelinePostEntity> CreateImagePost(long timelineId, long authorId, byte[] imageData, TimelinePostCommonProperties? properties = null);
/// <summary>
/// Delete a post.
@@ -128,17 +137,18 @@ namespace Timeline.Services
private readonly ILogger<TimelinePostService> _logger;
private readonly DatabaseContext _database;
private readonly IBasicTimelineService _basicTimelineService;
- private readonly IUserService _userService;
+ private readonly IBasicUserService _basicUserService;
private readonly IDataManager _dataManager;
private readonly IImageValidator _imageValidator;
private readonly IClock _clock;
+ private readonly ColorValidator _colorValidator = new ColorValidator();
- public TimelinePostService(ILogger<TimelinePostService> logger, DatabaseContext database, IBasicTimelineService basicTimelineService, IUserService userService, IDataManager dataManager, IImageValidator imageValidator, IClock clock)
+ public TimelinePostService(ILogger<TimelinePostService> logger, DatabaseContext database, IBasicTimelineService basicTimelineService, IBasicUserService basicUserService, IDataManager dataManager, IImageValidator imageValidator, IClock clock)
{
_logger = logger;
_database = database;
_basicTimelineService = basicTimelineService;
- _userService = userService;
+ _basicUserService = basicUserService;
_dataManager = dataManager;
_imageValidator = imageValidator;
_clock = clock;
@@ -150,6 +160,12 @@ namespace Timeline.Services
throw new TimelineNotExistException(timelineId);
}
+ private async Task CheckUserExistence(long userId)
+ {
+ if (!await _basicUserService.CheckUserExistence(userId))
+ throw new UserNotExistException(userId);
+ }
+
public async Task<List<TimelinePostEntity>> GetPosts(long timelineId, DateTime? modifiedSince = null, bool includeDeleted = false)
{
await CheckTimelineExistence(timelineId);
@@ -238,79 +254,77 @@ namespace Timeline.Services
};
}
- public async Task<TimelinePostEntity> CreateTextPost(long timelineId, long authorId, string text, DateTime? time)
+ private async Task<TimelinePostEntity> GeneralCreatePost(long timelineId, long authorId, TimelinePostCommonProperties? properties, Func<TimelinePostEntity, Task> saveContent)
{
- if (text is null)
- throw new ArgumentNullException(nameof(text));
+ if (properties is not null)
+ {
+ if (!_colorValidator.Validate(properties.Color, out var message))
+ {
+ throw new ArgumentException(message, nameof(properties));
+ }
+ properties.Time = properties.Time?.MyToUtc();
+ }
await CheckTimelineExistence(timelineId);
-
- time = time?.MyToUtc();
-
- var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync();
-
- var author = await _userService.GetUser(authorId);
+ await CheckUserExistence(authorId);
var currentTime = _clock.GetCurrentTime();
- var finalTime = time ?? currentTime;
-
- timelineEntity.CurrentPostLocalId += 1;
+ var finalTime = properties?.Time ?? currentTime;
var postEntity = new TimelinePostEntity
{
- LocalId = timelineEntity.CurrentPostLocalId,
- ContentType = TimelinePostContentTypes.Text,
- Content = text,
AuthorId = authorId,
TimelineId = timelineId,
Time = finalTime,
- LastUpdated = currentTime
+ LastUpdated = currentTime,
+ Color = properties?.Color
};
+
+ await saveContent(postEntity);
+
+ var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync();
+ timelineEntity.CurrentPostLocalId += 1;
+ postEntity.LocalId = timelineEntity.CurrentPostLocalId;
+
_database.TimelinePosts.Add(postEntity);
+
await _database.SaveChangesAsync();
return postEntity;
}
- public async Task<TimelinePostEntity> CreateImagePost(long timelineId, long authorId, byte[] data, DateTime? time)
+ public async Task<TimelinePostEntity> CreateTextPost(long timelineId, long authorId, string text, TimelinePostCommonProperties? properties = null)
{
- if (data is null)
- throw new ArgumentNullException(nameof(data));
-
- await CheckTimelineExistence(timelineId);
-
- time = time?.MyToUtc();
-
- var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync();
-
- var author = await _userService.GetUser(authorId);
-
- var imageFormat = await _imageValidator.Validate(data);
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
- var imageFormatText = imageFormat.DefaultMimeType;
+ return await GeneralCreatePost(timelineId, authorId, properties, (entity) =>
+ {
+ entity.ContentType = TimelinePostContentTypes.Text;
+ entity.Content = text;
- var tag = await _dataManager.RetainEntry(data);
+ return Task.CompletedTask;
+ });
+ }
- var currentTime = _clock.GetCurrentTime();
- var finalTime = time ?? currentTime;
+ public async Task<TimelinePostEntity> CreateImagePost(long timelineId, long authorId, byte[] data, TimelinePostCommonProperties? properties = null)
+ {
+ if (data is null)
+ throw new ArgumentNullException(nameof(data));
- timelineEntity.CurrentPostLocalId += 1;
+ await CheckTimelineExistence(timelineId);
- var postEntity = new TimelinePostEntity
+ return await GeneralCreatePost(timelineId, authorId, properties, async (entity) =>
{
- LocalId = timelineEntity.CurrentPostLocalId,
- ContentType = TimelinePostContentTypes.Image,
- Content = tag,
- ExtraContent = imageFormatText,
- AuthorId = authorId,
- TimelineId = timelineId,
- Time = finalTime,
- LastUpdated = currentTime
- };
- _database.TimelinePosts.Add(postEntity);
- await _database.SaveChangesAsync();
+ var imageFormat = await _imageValidator.Validate(data);
+ var imageFormatText = imageFormat.DefaultMimeType;
- return postEntity;
+ var tag = await _dataManager.RetainEntry(data);
+
+ entity.ContentType = TimelinePostContentTypes.Image;
+ entity.Content = tag;
+ entity.ExtraContent = imageFormatText;
+ });
}
public async Task DeletePost(long timelineId, long postId)