diff options
author | crupest <crupest@outlook.com> | 2021-02-02 18:59:41 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-02-02 18:59:41 +0800 |
commit | 0a0a61b60544a135a61394953bb5bb9dbbfeb241 (patch) | |
tree | 6e0ded513facfa3b8558aa8996284a10503e3099 | |
parent | 27e6b7be9bce006da6aae651d9903573cf3fd180 (diff) | |
download | timeline-0a0a61b60544a135a61394953bb5bb9dbbfeb241.tar.gz timeline-0a0a61b60544a135a61394953bb5bb9dbbfeb241.tar.bz2 timeline-0a0a61b60544a135a61394953bb5bb9dbbfeb241.zip |
...
29 files changed, 559 insertions, 440 deletions
diff --git a/BackEnd/Timeline/Entities/TimelineEntity.cs b/BackEnd/Timeline/Entities/TimelineEntity.cs index 3e592673..23859cb3 100644 --- a/BackEnd/Timeline/Entities/TimelineEntity.cs +++ b/BackEnd/Timeline/Entities/TimelineEntity.cs @@ -41,6 +41,9 @@ namespace Timeline.Entities [Column("visibility")]
public TimelineVisibility Visibility { get; set; }
+ [Column("color")]
+ public string? Color { get; set; }
+
[Column("create_time")]
public DateTime CreateTime { get; set; }
diff --git a/BackEnd/Timeline/Entities/TimelinePostEntity.cs b/BackEnd/Timeline/Entities/TimelinePostEntity.cs index 07367fba..39b11a5b 100644 --- a/BackEnd/Timeline/Entities/TimelinePostEntity.cs +++ b/BackEnd/Timeline/Entities/TimelinePostEntity.cs @@ -34,6 +34,9 @@ namespace Timeline.Entities [Column("extra_content")]
public string? ExtraContent { get; set; }
+ [Column("color")]
+ public string? Color { get; set; }
+
[Column("time")]
public DateTime Time { get; set; }
diff --git a/BackEnd/Timeline/Models/Http/HttpAutoMapperProfile.cs b/BackEnd/Timeline/Models/Http/HttpAutoMapperProfile.cs new file mode 100644 index 00000000..426379b8 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpAutoMapperProfile.cs @@ -0,0 +1,15 @@ +using AutoMapper;
+using Timeline.Services;
+
+namespace Timeline.Models.Http
+{
+
+ public class HttpAutoMapperProfile : Profile
+ {
+ public HttpAutoMapperProfile()
+ {
+ CreateMap<HttpUserPatchRequest, ModifyUserParams>();
+ CreateMap<HttpTimelinePatchRequest, TimelineChangePropertyParams>();
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/BookmarkTimeline.cs b/BackEnd/Timeline/Models/Http/HttpBookmarkTimelineMoveRequest.cs index 14be1112..14be1112 100644 --- a/BackEnd/Timeline/Models/Http/BookmarkTimeline.cs +++ b/BackEnd/Timeline/Models/Http/HttpBookmarkTimelineMoveRequest.cs diff --git a/BackEnd/Timeline/Models/Http/HttpChangePasswordRequest.cs b/BackEnd/Timeline/Models/Http/HttpChangePasswordRequest.cs new file mode 100644 index 00000000..0397d7ce --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpChangePasswordRequest.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations;
+using Timeline.Controllers;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Request model for <see cref="UserController.ChangePassword(HttpChangePasswordRequest)"/>.
+ /// </summary>
+ public class HttpChangePasswordRequest
+ {
+ /// <summary>
+ /// Old password.
+ /// </summary>
+ [Required(AllowEmptyStrings = false)]
+ public string OldPassword { get; set; } = default!;
+
+ /// <summary>
+ /// New password.
+ /// </summary>
+ [Required(AllowEmptyStrings = false)]
+ public string NewPassword { get; set; } = default!;
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpCreateTokenRequest.cs b/BackEnd/Timeline/Models/Http/HttpCreateTokenRequest.cs new file mode 100644 index 00000000..2a20d490 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpCreateTokenRequest.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations;
+using Timeline.Controllers;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Request model for <see cref="TokenController.Create(HttpCreateTokenRequest)"/>.
+ /// </summary>
+ public class HttpCreateTokenRequest
+ {
+ /// <summary>
+ /// The username.
+ /// </summary>
+ public string Username { get; set; } = default!;
+ /// <summary>
+ /// The password.
+ /// </summary>
+ public string Password { get; set; } = default!;
+ /// <summary>
+ /// Optional token validation period. In days. If not specified, server will use a default one.
+ /// </summary>
+ [Range(1, 365)]
+ public int? Expire { get; set; }
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpCreateTokenResponse.cs b/BackEnd/Timeline/Models/Http/HttpCreateTokenResponse.cs new file mode 100644 index 00000000..78dd43c5 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpCreateTokenResponse.cs @@ -0,0 +1,19 @@ +using Timeline.Controllers;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Response model for <see cref="TokenController.Create(HttpCreateTokenRequest)"/>.
+ /// </summary>
+ public class HttpCreateTokenResponse
+ {
+ /// <summary>
+ /// The token created.
+ /// </summary>
+ public string Token { get; set; } = default!;
+ /// <summary>
+ /// The user owning the token.
+ /// </summary>
+ public HttpUser User { get; set; } = default!;
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpCreateUserRequest.cs b/BackEnd/Timeline/Models/Http/HttpCreateUserRequest.cs new file mode 100644 index 00000000..7b221f73 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpCreateUserRequest.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations;
+using Timeline.Controllers;
+using Timeline.Models.Validation;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Request model for <see cref="UserController.CreateUser(HttpCreateUserRequest)"/>.
+ /// </summary>
+ public class HttpCreateUserRequest
+ {
+ /// <summary>
+ /// Username of the new user.
+ /// </summary>
+ [Required, Username]
+ public string Username { get; set; } = default!;
+
+ /// <summary>
+ /// Password of the new user.
+ /// </summary>
+ [Required, MinLength(1)]
+ public string Password { get; set; } = default!;
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HighlightTimeline.cs b/BackEnd/Timeline/Models/Http/HttpHighlightTimelineMoveRequest.cs index 5af0e528..5af0e528 100644 --- a/BackEnd/Timeline/Models/Http/HighlightTimeline.cs +++ b/BackEnd/Timeline/Models/Http/HttpHighlightTimelineMoveRequest.cs diff --git a/BackEnd/Timeline/Models/Http/HttpTimeline.cs b/BackEnd/Timeline/Models/Http/HttpTimeline.cs new file mode 100644 index 00000000..87ebf0bb --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpTimeline.cs @@ -0,0 +1,89 @@ +using System;
+using System.Collections.Generic;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Info of a timeline.
+ /// </summary>
+ public class HttpTimeline
+ {
+ public HttpTimeline() { }
+
+ public HttpTimeline(string uniqueId, string title, string name, DateTime nameLastModifed, string description, HttpUser owner, TimelineVisibility visibility, List<HttpUser> members, string? color, DateTime createTime, DateTime lastModified, bool isHighlight, bool isBookmark, HttpTimelineLinks links)
+ {
+ UniqueId = uniqueId;
+ Title = title;
+ Name = name;
+ NameLastModifed = nameLastModifed;
+ Description = description;
+ Owner = owner;
+ Visibility = visibility;
+ Members = members;
+ Color = color;
+ CreateTime = createTime;
+ LastModified = lastModified;
+ IsHighlight = isHighlight;
+ IsBookmark = isBookmark;
+ _links = links;
+ }
+
+ /// <summary>
+ /// Unique id.
+ /// </summary>
+ public string UniqueId { get; set; } = default!;
+ /// <summary>
+ /// Title.
+ /// </summary>
+ public string Title { get; set; } = default!;
+ /// <summary>
+ /// Name of timeline.
+ /// </summary>
+ public string Name { get; set; } = default!;
+ /// <summary>
+ /// Last modified time of timeline name.
+ /// </summary>
+ public DateTime NameLastModifed { get; set; } = default!;
+ /// <summary>
+ /// Timeline description.
+ /// </summary>
+ public string Description { get; set; } = default!;
+ /// <summary>
+ /// Owner of the timeline.
+ /// </summary>
+ public HttpUser Owner { get; set; } = default!;
+ /// <summary>
+ /// Visibility of the timeline.
+ /// </summary>
+ public TimelineVisibility Visibility { get; set; }
+#pragma warning disable CA2227 // Collection properties should be read only
+ /// <summary>
+ /// Members of timeline.
+ /// </summary>
+ public List<HttpUser> Members { get; set; } = default!;
+#pragma warning restore CA2227 // Collection properties should be read only
+ /// <summary>
+ /// Color of timeline.
+ /// </summary>
+ public string? Color { get; set; }
+ /// <summary>
+ /// Create time of timeline.
+ /// </summary>
+ public DateTime CreateTime { get; set; } = default!;
+ /// <summary>
+ /// Last modified time of timeline.
+ /// </summary>
+ public DateTime LastModified { get; set; } = default!;
+
+ public bool IsHighlight { get; set; }
+
+ public bool IsBookmark { get; set; }
+
+#pragma warning disable CA1707 // Identifiers should not contain underscores
+ /// <summary>
+ /// Related links.
+ /// </summary>
+ public HttpTimelineLinks _links { get; set; } = default!;
+#pragma warning restore CA1707 // Identifiers should not contain underscores
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpTimelineCreateRequest.cs b/BackEnd/Timeline/Models/Http/HttpTimelineCreateRequest.cs new file mode 100644 index 00000000..e9f57e46 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpTimelineCreateRequest.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations;
+using Timeline.Models.Validation;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Create timeline request model.
+ /// </summary>
+ public class HttpTimelineCreateRequest
+ {
+ /// <summary>
+ /// Name of the new timeline. Must be a valid name.
+ /// </summary>
+ [Required]
+ [TimelineName]
+ public string Name { get; set; } = default!;
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpTimelineLinks.cs b/BackEnd/Timeline/Models/Http/HttpTimelineLinks.cs new file mode 100644 index 00000000..722c1338 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpTimelineLinks.cs @@ -0,0 +1,26 @@ +namespace Timeline.Models.Http
+{
+
+ /// <summary>
+ /// Related links for timeline.
+ /// </summary>
+ public class HttpTimelineLinks
+ {
+ public HttpTimelineLinks() { }
+
+ public HttpTimelineLinks(string self, string posts)
+ {
+ Self = self;
+ Posts = posts;
+ }
+
+ /// <summary>
+ /// Self.
+ /// </summary>
+ public string Self { get; set; } = default!;
+ /// <summary>
+ /// Posts url.
+ /// </summary>
+ public string Posts { get; set; } = default!;
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpTimelinePatchRequest.cs b/BackEnd/Timeline/Models/Http/HttpTimelinePatchRequest.cs new file mode 100644 index 00000000..9accb6fc --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpTimelinePatchRequest.cs @@ -0,0 +1,37 @@ +using Timeline.Models.Validation;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Patch timeline request model.
+ /// </summary>
+ public class HttpTimelinePatchRequest
+ {
+ /// <summary>
+ /// New name. Null for not change.
+ /// </summary>
+ [TimelineName]
+ public string? Name { get; set; }
+
+ /// <summary>
+ /// New title. Null for not change.
+ /// </summary>
+ public string? Title { get; set; }
+
+ /// <summary>
+ /// New description. Null for not change.
+ /// </summary>
+ public string? Description { get; set; }
+
+ /// <summary>
+ /// New visibility. Null for not change.
+ /// </summary>
+ public TimelineVisibility? Visibility { get; set; }
+
+ /// <summary>
+ /// New color. Null for not change.
+ /// </summary>
+ [Color]
+ public string? Color { get; set; }
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpTimelinePost.cs b/BackEnd/Timeline/Models/Http/HttpTimelinePost.cs new file mode 100644 index 00000000..a563bea0 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpTimelinePost.cs @@ -0,0 +1,47 @@ +using System;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Info of a post.
+ /// </summary>
+ public class HttpTimelinePost
+ {
+ public HttpTimelinePost() { }
+
+ public HttpTimelinePost(long id, HttpTimelinePostContent? content, bool deleted, DateTime time, HttpUser? author, DateTime lastUpdated)
+ {
+ Id = id;
+ Content = content;
+ Deleted = deleted;
+ Time = time;
+ Author = author;
+ LastUpdated = lastUpdated;
+ }
+
+ /// <summary>
+ /// Post id.
+ /// </summary>
+ public long Id { get; set; }
+ /// <summary>
+ /// Content of the post. May be null if post is deleted.
+ /// </summary>
+ public HttpTimelinePostContent? Content { get; set; }
+ /// <summary>
+ /// True if post is deleted.
+ /// </summary>
+ public bool Deleted { get; set; }
+ /// <summary>
+ /// Post time.
+ /// </summary>
+ public DateTime Time { get; set; }
+ /// <summary>
+ /// The author. May be null if the user has been deleted.
+ /// </summary>
+ public HttpUser? Author { get; set; } = default!;
+ /// <summary>
+ /// Last updated time.
+ /// </summary>
+ public DateTime LastUpdated { get; set; } = default!;
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpTimelinePostContent.cs b/BackEnd/Timeline/Models/Http/HttpTimelinePostContent.cs new file mode 100644 index 00000000..55ff1ac2 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpTimelinePostContent.cs @@ -0,0 +1,35 @@ +namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Info of post content.
+ /// </summary>
+ public class HttpTimelinePostContent
+ {
+ public HttpTimelinePostContent() { }
+
+ public HttpTimelinePostContent(string type, string? text, string? url, string? eTag)
+ {
+ Type = type;
+ Text = text;
+ Url = url;
+ ETag = eTag;
+ }
+
+ /// <summary>
+ /// Type of the post content.
+ /// </summary>
+ public string Type { get; set; } = default!;
+ /// <summary>
+ /// If post is of text type. This is the text.
+ /// </summary>
+ public string? Text { get; set; }
+ /// <summary>
+ /// If post is of image type. This is the image url.
+ /// </summary>
+ public string? Url { get; set; }
+ /// <summary>
+ /// If post has data (currently it means it's a image post), this is the data etag.
+ /// </summary>
+ public string? ETag { get; set; }
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpTimelinePostCreateRequest.cs b/BackEnd/Timeline/Models/Http/HttpTimelinePostCreateRequest.cs new file mode 100644 index 00000000..cfbec029 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpTimelinePostCreateRequest.cs @@ -0,0 +1,19 @@ +using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace Timeline.Models.Http
+{
+ public class HttpTimelinePostCreateRequest
+ {
+ /// <summary>
+ /// Content of the new post.
+ /// </summary>
+ [Required]
+ public HttpTimelinePostCreateRequestContent Content { get; set; } = default!;
+
+ /// <summary>
+ /// Time of the post. If not set, current time will be used.
+ /// </summary>
+ public DateTime? Time { get; set; }
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpTimelinePostCreateRequestContent.cs b/BackEnd/Timeline/Models/Http/HttpTimelinePostCreateRequestContent.cs new file mode 100644 index 00000000..f4b300a9 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpTimelinePostCreateRequestContent.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Content of post create request.
+ /// </summary>
+ public class HttpTimelinePostCreateRequestContent
+ {
+ /// <summary>
+ /// Type of post content.
+ /// </summary>
+ [Required]
+ public string Type { get; set; } = default!;
+ /// <summary>
+ /// If post is of text type, this is the text.
+ /// </summary>
+ public string? Text { get; set; }
+ /// <summary>
+ /// If post is of image type, this is base64 of image data.
+ /// </summary>
+ public string? Data { get; set; }
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/User.cs b/BackEnd/Timeline/Models/Http/HttpUser.cs index 994c08bf..4b82264c 100644 --- a/BackEnd/Timeline/Models/Http/User.cs +++ b/BackEnd/Timeline/Models/Http/HttpUser.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic;
+using System.Collections.Generic;
namespace Timeline.Models.Http
{
@@ -43,32 +43,4 @@ namespace Timeline.Models.Http public HttpUserLinks _links { get; set; } = default!;
#pragma warning restore CA1707 // Identifiers should not contain underscores
}
-
- /// <summary>
- /// Related links for user.
- /// </summary>
- public class HttpUserLinks
- {
- public HttpUserLinks() { }
-
- public HttpUserLinks(string self, string avatar, string timeline)
- {
- Self = self;
- Avatar = avatar;
- Timeline = timeline;
- }
-
- /// <summary>
- /// Self.
- /// </summary>
- public string Self { get; set; } = default!;
- /// <summary>
- /// Avatar url.
- /// </summary>
- public string Avatar { get; set; } = default!;
- /// <summary>
- /// Personal timeline url.
- /// </summary>
- public string Timeline { get; set; } = default!;
- }
}
diff --git a/BackEnd/Timeline/Models/Http/HttpUserLinks.cs b/BackEnd/Timeline/Models/Http/HttpUserLinks.cs new file mode 100644 index 00000000..d5f909c2 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpUserLinks.cs @@ -0,0 +1,31 @@ +namespace Timeline.Models.Http
+{
+
+ /// <summary>
+ /// Related links for user.
+ /// </summary>
+ public class HttpUserLinks
+ {
+ public HttpUserLinks() { }
+
+ public HttpUserLinks(string self, string avatar, string timeline)
+ {
+ Self = self;
+ Avatar = avatar;
+ Timeline = timeline;
+ }
+
+ /// <summary>
+ /// Self.
+ /// </summary>
+ public string Self { get; set; } = default!;
+ /// <summary>
+ /// Avatar url.
+ /// </summary>
+ public string Avatar { get; set; } = default!;
+ /// <summary>
+ /// Personal timeline url.
+ /// </summary>
+ public string Timeline { get; set; } = default!;
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpUserPatchRequest.cs b/BackEnd/Timeline/Models/Http/HttpUserPatchRequest.cs new file mode 100644 index 00000000..e7a3d8e3 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpUserPatchRequest.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations;
+using Timeline.Controllers;
+using Timeline.Models.Validation;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Request model for <see cref="UserController.Patch(HttpUserPatchRequest, string)"/>.
+ /// </summary>
+ public class HttpUserPatchRequest
+ {
+ /// <summary>
+ /// New username. Null if not change. Need to be administrator.
+ /// </summary>
+ [Username]
+ public string? Username { get; set; }
+
+ /// <summary>
+ /// New password. Null if not change. Need to be administrator.
+ /// </summary>
+ [MinLength(1)]
+ public string? Password { get; set; }
+
+ /// <summary>
+ /// New nickname. Null if not change. Need to be administrator to change other's.
+ /// </summary>
+ [Nickname]
+ public string? Nickname { get; set; }
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpVerifyTokenRequest.cs b/BackEnd/Timeline/Models/Http/HttpVerifyTokenRequest.cs new file mode 100644 index 00000000..98f86455 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpVerifyTokenRequest.cs @@ -0,0 +1,15 @@ +using Timeline.Controllers;
+
+namespace Timeline.Models.Http
+{
+ /// <summary>
+ /// Request model for <see cref="TokenController.Verify(HttpVerifyTokenRequest)"/>.
+ /// </summary>
+ public class HttpVerifyTokenRequest
+ {
+ /// <summary>
+ /// The token to verify.
+ /// </summary>
+ public string Token { get; set; } = default!;
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/HttpVerifyTokenResponse.cs b/BackEnd/Timeline/Models/Http/HttpVerifyTokenResponse.cs new file mode 100644 index 00000000..ae8eb018 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpVerifyTokenResponse.cs @@ -0,0 +1,16 @@ +using Timeline.Controllers;
+
+namespace Timeline.Models.Http
+{
+
+ /// <summary>
+ /// Response model for <see cref="TokenController.Verify(HttpVerifyTokenRequest)"/>.
+ /// </summary>
+ public class HttpVerifyTokenResponse
+ {
+ /// <summary>
+ /// The user owning the token.
+ /// </summary>
+ public HttpUser User { get; set; } = default!;
+ }
+}
diff --git a/BackEnd/Timeline/Models/Http/Timeline.cs b/BackEnd/Timeline/Models/Http/Timeline.cs deleted file mode 100644 index 5e5889f6..00000000 --- a/BackEnd/Timeline/Models/Http/Timeline.cs +++ /dev/null @@ -1,183 +0,0 @@ -using System;
-using System.Collections.Generic;
-
-namespace Timeline.Models.Http
-{
- /// <summary>
- /// Info of post content.
- /// </summary>
- public class HttpTimelinePostContent
- {
- public HttpTimelinePostContent() { }
-
- public HttpTimelinePostContent(string type, string? text, string? url, string? eTag)
- {
- Type = type;
- Text = text;
- Url = url;
- ETag = eTag;
- }
-
- /// <summary>
- /// Type of the post content.
- /// </summary>
- public string Type { get; set; } = default!;
- /// <summary>
- /// If post is of text type. This is the text.
- /// </summary>
- public string? Text { get; set; }
- /// <summary>
- /// If post is of image type. This is the image url.
- /// </summary>
- public string? Url { get; set; }
- /// <summary>
- /// If post has data (currently it means it's a image post), this is the data etag.
- /// </summary>
- public string? ETag { get; set; }
- }
-
- /// <summary>
- /// Info of a post.
- /// </summary>
- public class HttpTimelinePost
- {
- public HttpTimelinePost() { }
-
- public HttpTimelinePost(long id, HttpTimelinePostContent? content, bool deleted, DateTime time, HttpUser? author, DateTime lastUpdated)
- {
- Id = id;
- Content = content;
- Deleted = deleted;
- Time = time;
- Author = author;
- LastUpdated = lastUpdated;
- }
-
- /// <summary>
- /// Post id.
- /// </summary>
- public long Id { get; set; }
- /// <summary>
- /// Content of the post. May be null if post is deleted.
- /// </summary>
- public HttpTimelinePostContent? Content { get; set; }
- /// <summary>
- /// True if post is deleted.
- /// </summary>
- public bool Deleted { get; set; }
- /// <summary>
- /// Post time.
- /// </summary>
- public DateTime Time { get; set; }
- /// <summary>
- /// The author. May be null if the user has been deleted.
- /// </summary>
- public HttpUser? Author { get; set; } = default!;
- /// <summary>
- /// Last updated time.
- /// </summary>
- public DateTime LastUpdated { get; set; } = default!;
- }
-
- /// <summary>
- /// Info of a timeline.
- /// </summary>
- public class HttpTimeline
- {
- public HttpTimeline() { }
-
- public HttpTimeline(string uniqueId, string title, string name, DateTime nameLastModifed, string description, HttpUser owner, TimelineVisibility visibility, List<HttpUser> members, DateTime createTime, DateTime lastModified, bool isHighlight, bool isBookmark, HttpTimelineLinks links)
- {
- UniqueId = uniqueId;
- Title = title;
- Name = name;
- NameLastModifed = nameLastModifed;
- Description = description;
- Owner = owner;
- Visibility = visibility;
- Members = members;
- CreateTime = createTime;
- LastModified = lastModified;
- IsHighlight = isHighlight;
- IsBookmark = isBookmark;
- _links = links;
- }
-
- /// <summary>
- /// Unique id.
- /// </summary>
- public string UniqueId { get; set; } = default!;
- /// <summary>
- /// Title.
- /// </summary>
- public string Title { get; set; } = default!;
- /// <summary>
- /// Name of timeline.
- /// </summary>
- public string Name { get; set; } = default!;
- /// <summary>
- /// Last modified time of timeline name.
- /// </summary>
- public DateTime NameLastModifed { get; set; } = default!;
- /// <summary>
- /// Timeline description.
- /// </summary>
- public string Description { get; set; } = default!;
- /// <summary>
- /// Owner of the timeline.
- /// </summary>
- public HttpUser Owner { get; set; } = default!;
- /// <summary>
- /// Visibility of the timeline.
- /// </summary>
- public TimelineVisibility Visibility { get; set; }
-#pragma warning disable CA2227 // Collection properties should be read only
- /// <summary>
- /// Members of timeline.
- /// </summary>
- public List<HttpUser> Members { get; set; } = default!;
-#pragma warning restore CA2227 // Collection properties should be read only
- /// <summary>
- /// Create time of timeline.
- /// </summary>
- public DateTime CreateTime { get; set; } = default!;
- /// <summary>
- /// Last modified time of timeline.
- /// </summary>
- public DateTime LastModified { get; set; } = default!;
-
- public bool IsHighlight { get; set; }
-
- public bool IsBookmark { get; set; }
-
-#pragma warning disable CA1707 // Identifiers should not contain underscores
- /// <summary>
- /// Related links.
- /// </summary>
- public HttpTimelineLinks _links { get; set; } = default!;
-#pragma warning restore CA1707 // Identifiers should not contain underscores
- }
-
- /// <summary>
- /// Related links for timeline.
- /// </summary>
- public class HttpTimelineLinks
- {
- public HttpTimelineLinks() { }
-
- public HttpTimelineLinks(string self, string posts)
- {
- Self = self;
- Posts = posts;
- }
-
- /// <summary>
- /// Self.
- /// </summary>
- public string Self { get; set; } = default!;
- /// <summary>
- /// Posts url.
- /// </summary>
- public string Posts { get; set; } = default!;
- }
-}
diff --git a/BackEnd/Timeline/Models/Http/TimelineController.cs b/BackEnd/Timeline/Models/Http/TimelineController.cs deleted file mode 100644 index 79be1826..00000000 --- a/BackEnd/Timeline/Models/Http/TimelineController.cs +++ /dev/null @@ -1,90 +0,0 @@ -using AutoMapper;
-using System;
-using System.ComponentModel.DataAnnotations;
-using Timeline.Models.Validation;
-using Timeline.Services;
-
-namespace Timeline.Models.Http
-{
- /// <summary>
- /// Content of post create request.
- /// </summary>
- public class HttpTimelinePostCreateRequestContent
- {
- /// <summary>
- /// Type of post content.
- /// </summary>
- [Required]
- public string Type { get; set; } = default!;
- /// <summary>
- /// If post is of text type, this is the text.
- /// </summary>
- public string? Text { get; set; }
- /// <summary>
- /// If post is of image type, this is base64 of image data.
- /// </summary>
- public string? Data { get; set; }
- }
-
- public class HttpTimelinePostCreateRequest
- {
- /// <summary>
- /// Content of the new post.
- /// </summary>
- [Required]
- public HttpTimelinePostCreateRequestContent Content { get; set; } = default!;
-
- /// <summary>
- /// Time of the post. If not set, current time will be used.
- /// </summary>
- public DateTime? Time { get; set; }
- }
-
- /// <summary>
- /// Create timeline request model.
- /// </summary>
- public class HttpTimelineCreateRequest
- {
- /// <summary>
- /// Name of the new timeline. Must be a valid name.
- /// </summary>
- [Required]
- [TimelineName]
- public string Name { get; set; } = default!;
- }
-
- /// <summary>
- /// Patch timeline request model.
- /// </summary>
- public class HttpTimelinePatchRequest
- {
- /// <summary>
- /// New name. Null for not change.
- /// </summary>
- [TimelineName]
- public string? Name { get; set; }
-
- /// <summary>
- /// New title. Null for not change.
- /// </summary>
- public string? Title { get; set; }
-
- /// <summary>
- /// New description. Null for not change.
- /// </summary>
- public string? Description { get; set; }
-
- /// <summary>
- /// New visibility. Null for not change.
- /// </summary>
- public TimelineVisibility? Visibility { get; set; }
- }
-
- public class HttpTimelineControllerAutoMapperProfile : Profile
- {
- public HttpTimelineControllerAutoMapperProfile()
- {
- CreateMap<HttpTimelinePatchRequest, TimelineChangePropertyParams>();
- }
- }
-}
diff --git a/BackEnd/Timeline/Models/Http/TokenController.cs b/BackEnd/Timeline/Models/Http/TokenController.cs deleted file mode 100644 index a5cbba14..00000000 --- a/BackEnd/Timeline/Models/Http/TokenController.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.ComponentModel.DataAnnotations;
-using Timeline.Controllers;
-
-namespace Timeline.Models.Http
-{
- /// <summary>
- /// Request model for <see cref="TokenController.Create(HttpCreateTokenRequest)"/>.
- /// </summary>
- public class HttpCreateTokenRequest
- {
- /// <summary>
- /// The username.
- /// </summary>
- public string Username { get; set; } = default!;
- /// <summary>
- /// The password.
- /// </summary>
- public string Password { get; set; } = default!;
- /// <summary>
- /// Optional token validation period. In days. If not specified, server will use a default one.
- /// </summary>
- [Range(1, 365)]
- public int? Expire { get; set; }
- }
-
- /// <summary>
- /// Response model for <see cref="TokenController.Create(HttpCreateTokenRequest)"/>.
- /// </summary>
- public class HttpCreateTokenResponse
- {
- /// <summary>
- /// The token created.
- /// </summary>
- public string Token { get; set; } = default!;
- /// <summary>
- /// The user owning the token.
- /// </summary>
- public HttpUser User { get; set; } = default!;
- }
-
- /// <summary>
- /// Request model for <see cref="TokenController.Verify(HttpVerifyTokenRequest)"/>.
- /// </summary>
- public class HttpVerifyTokenRequest
- {
- /// <summary>
- /// The token to verify.
- /// </summary>
- public string Token { get; set; } = default!;
- }
-
- /// <summary>
- /// Response model for <see cref="TokenController.Verify(HttpVerifyTokenRequest)"/>.
- /// </summary>
- public class HttpVerifyTokenResponse
- {
- /// <summary>
- /// The user owning the token.
- /// </summary>
- public HttpUser User { get; set; } = default!;
- }
-}
diff --git a/BackEnd/Timeline/Models/Http/UserController.cs b/BackEnd/Timeline/Models/Http/UserController.cs deleted file mode 100644 index 1b4d09ec..00000000 --- a/BackEnd/Timeline/Models/Http/UserController.cs +++ /dev/null @@ -1,76 +0,0 @@ -using AutoMapper;
-using System.ComponentModel.DataAnnotations;
-using Timeline.Controllers;
-using Timeline.Models.Validation;
-using Timeline.Services;
-
-namespace Timeline.Models.Http
-{
- /// <summary>
- /// Request model for <see cref="UserController.Patch(HttpUserPatchRequest, string)"/>.
- /// </summary>
- public class HttpUserPatchRequest
- {
- /// <summary>
- /// New username. Null if not change. Need to be administrator.
- /// </summary>
- [Username]
- public string? Username { get; set; }
-
- /// <summary>
- /// New password. Null if not change. Need to be administrator.
- /// </summary>
- [MinLength(1)]
- public string? Password { get; set; }
-
- /// <summary>
- /// New nickname. Null if not change. Need to be administrator to change other's.
- /// </summary>
- [Nickname]
- public string? Nickname { get; set; }
- }
-
- /// <summary>
- /// Request model for <see cref="UserController.CreateUser(HttpCreateUserRequest)"/>.
- /// </summary>
- public class HttpCreateUserRequest
- {
- /// <summary>
- /// Username of the new user.
- /// </summary>
- [Required, Username]
- public string Username { get; set; } = default!;
-
- /// <summary>
- /// Password of the new user.
- /// </summary>
- [Required, MinLength(1)]
- public string Password { get; set; } = default!;
- }
-
- /// <summary>
- /// Request model for <see cref="UserController.ChangePassword(HttpChangePasswordRequest)"/>.
- /// </summary>
- public class HttpChangePasswordRequest
- {
- /// <summary>
- /// Old password.
- /// </summary>
- [Required(AllowEmptyStrings = false)]
- public string OldPassword { get; set; } = default!;
-
- /// <summary>
- /// New password.
- /// </summary>
- [Required(AllowEmptyStrings = false)]
- public string NewPassword { get; set; } = default!;
- }
-
- public class HttpUserControllerModelAutoMapperProfile : Profile
- {
- public HttpUserControllerModelAutoMapperProfile()
- {
- CreateMap<HttpUserPatchRequest, ModifyUserParams>();
- }
- }
-}
diff --git a/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs b/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs index 79a6fa1d..25abf0ba 100644 --- a/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs +++ b/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs @@ -42,6 +42,7 @@ namespace Timeline.Models.Mapper owner: await _userMapper.MapToHttp(entity.Owner, urlHelper),
visibility: entity.Visibility,
members: await _userMapper.MapToHttp(entity.Members.Select(m => m.User).ToList(), urlHelper),
+ color: entity.Color,
createTime: entity.CreateTime,
lastModified: entity.LastModified,
isHighlight: await _highlightTimelineService.IsHighlightTimeline(entity.Id),
diff --git a/BackEnd/Timeline/Models/Validation/ColorValidator.cs b/BackEnd/Timeline/Models/Validation/ColorValidator.cs new file mode 100644 index 00000000..c5ad833d --- /dev/null +++ b/BackEnd/Timeline/Models/Validation/ColorValidator.cs @@ -0,0 +1,40 @@ +using System;
+
+namespace Timeline.Models.Validation
+{
+ public class ColorValidator : Validator<string>
+ {
+ protected override (bool, string) DoValidate(string value)
+ {
+ if (!value.StartsWith('#'))
+ {
+ return (false, "Color must starts with '#'.");
+ }
+
+ if (value.Length != 7)
+ {
+ return (false, "A color string must have 7 chars.");
+ }
+
+ for (int i = 1; i < 7; i++)
+ {
+ var c = value[i];
+ if (!((c >= '0' && c <= '9') || (c >= 'a' || c <= 'f') || (c >= 'A' | c <= 'F')))
+ {
+ return (false, $"Char at index {i} is not a hex character.");
+ }
+ }
+
+ return (true, GetSuccessMessage());
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
+ public class ColorAttribute : ValidateWithAttribute
+ {
+ public ColorAttribute() : base(typeof(ColorValidator))
+ {
+
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Services/TimelineService.cs b/BackEnd/Timeline/Services/TimelineService.cs index f4141752..bed1c99b 100644 --- a/BackEnd/Timeline/Services/TimelineService.cs +++ b/BackEnd/Timeline/Services/TimelineService.cs @@ -53,6 +53,7 @@ namespace Timeline.Services public string? Title { get; set; }
public string? Description { get; set; }
public TimelineVisibility? Visibility { get; set; }
+ public string? Color { get; set; }
}
/// <summary>
@@ -186,6 +187,8 @@ namespace Timeline.Services private readonly TimelineNameValidator _timelineNameValidator = new TimelineNameValidator();
+ private readonly ColorValidator _colorValidator = new ColorValidator();
+
private void ValidateTimelineName(string name, string paramName)
{
if (!_timelineNameValidator.Validate(name, out var message))
@@ -212,6 +215,15 @@ namespace Timeline.Services if (newProperties.Name is not null)
ValidateTimelineName(newProperties.Name, nameof(newProperties));
+ if (newProperties.Color is not null)
+ {
+ var (result, message) = _colorValidator.Validate(newProperties.Color);
+ if (!result)
+ {
+ throw new ArgumentException(message, nameof(newProperties));
+ }
+ }
+
var entity = await _database.Timelines.Where(t => t.Id == id).SingleOrDefaultAsync();
if (entity is null)
@@ -251,6 +263,12 @@ namespace Timeline.Services entity.Visibility = newProperties.Visibility.Value;
}
+ if (newProperties.Color is not null)
+ {
+ changed = true;
+ entity.Color = newProperties.Color;
+ }
+
if (changed)
{
var currentTime = _clock.GetCurrentTime();
|