diff options
Diffstat (limited to 'BackEnd/Timeline/Services')
47 files changed, 1384 insertions, 244 deletions
diff --git a/BackEnd/Timeline/Services/BookmarkTimelineService.cs b/BackEnd/Timeline/Services/Api/BookmarkTimelineService.cs index 4930686e..0d4cc0a6 100644 --- a/BackEnd/Timeline/Services/BookmarkTimelineService.cs +++ b/BackEnd/Timeline/Services/Api/BookmarkTimelineService.cs @@ -4,9 +4,10 @@ using System.Collections.Generic; using System.Linq;
using System.Threading.Tasks;
using Timeline.Entities;
-using Timeline.Services.Exceptions;
+using Timeline.Services.Timeline;
+using Timeline.Services.User;
-namespace Timeline.Services
+namespace Timeline.Services.Api
{
[Serializable]
diff --git a/BackEnd/Timeline/Services/HighlightTimelineService.cs b/BackEnd/Timeline/Services/Api/HighlightTimelineService.cs index 557478c7..9ef8ea84 100644 --- a/BackEnd/Timeline/Services/HighlightTimelineService.cs +++ b/BackEnd/Timeline/Services/Api/HighlightTimelineService.cs @@ -4,9 +4,10 @@ using System.Collections.Generic; using System.Linq;
using System.Threading.Tasks;
using Timeline.Entities;
-using Timeline.Services.Exceptions;
+using Timeline.Services.Timeline;
+using Timeline.Services.User;
-namespace Timeline.Services
+namespace Timeline.Services.Api
{
[Serializable]
diff --git a/BackEnd/Timeline/Services/SearchService.cs b/BackEnd/Timeline/Services/Api/SearchService.cs index 680ef9e3..eec5001f 100644 --- a/BackEnd/Timeline/Services/SearchService.cs +++ b/BackEnd/Timeline/Services/Api/SearchService.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Threading.Tasks;
using Timeline.Entities;
-namespace Timeline.Services
+namespace Timeline.Services.Api
{
public class SearchResultItem<TItem>
{
diff --git a/BackEnd/Timeline/Services/DataManager.cs b/BackEnd/Timeline/Services/Data/DataManager.cs index b43b80f9..d9a4491d 100644 --- a/BackEnd/Timeline/Services/DataManager.cs +++ b/BackEnd/Timeline/Services/Data/DataManager.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Threading.Tasks;
using Timeline.Entities;
-namespace Timeline.Services
+namespace Timeline.Services.Data
{
/// <summary>
/// A data manager controlling data.
diff --git a/BackEnd/Timeline/Services/ETagGenerator.cs b/BackEnd/Timeline/Services/Data/ETagGenerator.cs index 4493e903..847c120b 100644 --- a/BackEnd/Timeline/Services/ETagGenerator.cs +++ b/BackEnd/Timeline/Services/Data/ETagGenerator.cs @@ -2,7 +2,7 @@ using System.Security.Cryptography;
using System.Threading.Tasks;
-namespace Timeline.Services
+namespace Timeline.Services.Data
{
public interface IETagGenerator
{
diff --git a/BackEnd/Timeline/Services/DatabaseManagement/TimelinePostContentToDataMigration.cs b/BackEnd/Timeline/Services/DatabaseManagement/TimelinePostContentToDataMigration.cs index 605223f3..f9a3418b 100644 --- a/BackEnd/Timeline/Services/DatabaseManagement/TimelinePostContentToDataMigration.cs +++ b/BackEnd/Timeline/Services/DatabaseManagement/TimelinePostContentToDataMigration.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks;
using Timeline.Entities;
using Timeline.Models;
+using Timeline.Services.Data;
namespace Timeline.Services.DatabaseManagement
{
diff --git a/BackEnd/Timeline/Services/EntityAlreadyExistException.cs b/BackEnd/Timeline/Services/EntityAlreadyExistException.cs new file mode 100644 index 00000000..2d3de368 --- /dev/null +++ b/BackEnd/Timeline/Services/EntityAlreadyExistException.cs @@ -0,0 +1,32 @@ +using System;
+
+namespace Timeline.Services
+{
+ /// <summary>
+ /// Thrown when an entity is already exists.
+ /// </summary>
+ /// <remarks>
+ /// For example, want to create a timeline but a timeline with the same name already exists.
+ /// </remarks>
+ [Serializable]
+ public class EntityAlreadyExistException : Exception
+ {
+ public EntityAlreadyExistException() : this(null, null, null, null) { }
+ public EntityAlreadyExistException(string? entityName) : this(entityName, null, null, null) { }
+ public EntityAlreadyExistException(string? entityName, Exception? inner) : this(entityName, null, null, inner) { }
+ public EntityAlreadyExistException(string? entityName, object? entity, Exception inner) : this(entityName, entity, null, inner) { }
+ public EntityAlreadyExistException(string? entityName, object? entity, string? message, Exception? inner) : base(message ?? Resource.ExceptionEntityAlreadyExist, inner)
+ {
+ EntityName = entityName;
+ Entity = entity;
+ }
+
+ protected EntityAlreadyExistException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+
+ public string? EntityName { get; }
+
+ public object? Entity { get; }
+ }
+}
diff --git a/BackEnd/Timeline/Services/EntityNotExistException.cs b/BackEnd/Timeline/Services/EntityNotExistException.cs new file mode 100644 index 00000000..39a4f545 --- /dev/null +++ b/BackEnd/Timeline/Services/EntityNotExistException.cs @@ -0,0 +1,27 @@ +using System;
+
+namespace Timeline.Services
+{
+ /// <summary>
+ /// Thrown when you want to get an entity that does not exist.
+ /// </summary>
+ /// <example>
+ /// For example, you want to get a timeline with given name but it does not exist.
+ /// </example>
+ [Serializable]
+ public class EntityNotExistException : Exception
+ {
+ public EntityNotExistException() : this(null, null) { }
+ public EntityNotExistException(string? entityName) : this(entityName, null) { }
+ public EntityNotExistException(string? entityName, Exception? inner) : this(entityName, null, inner) { }
+ public EntityNotExistException(string? entityName, string? message, Exception? inner) : base(message ?? Resource.ExceptionEntityNotExist, inner)
+ {
+ EntityName = entityName;
+ }
+ protected EntityNotExistException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+
+ public string? EntityName { get; }
+ }
+}
diff --git a/BackEnd/Timeline/Services/Exceptions/EntityAlreadyExistError.cs b/BackEnd/Timeline/Services/Exceptions/EntityAlreadyExistError.cs deleted file mode 100644 index 7db2e860..00000000 --- a/BackEnd/Timeline/Services/Exceptions/EntityAlreadyExistError.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System;
-using System.Globalization;
-using System.Text;
-
-namespace Timeline.Services.Exceptions
-{
- /// <summary>
- /// Thrown when an entity is already exists.
- /// </summary>
- /// <remarks>
- /// For example, want to create a timeline but a timeline with the same name already exists.
- /// </remarks>
- [Serializable]
- public class EntityAlreadyExistException : Exception
- {
- private readonly string? _entityName;
-
- public EntityAlreadyExistException() : this(null, null, null, null) { }
-
- public EntityAlreadyExistException(string? entityName) : this(entityName, null) { }
-
- public EntityAlreadyExistException(string? entityName, Exception? inner) : this(entityName, null, null, null, inner) { }
-
- public EntityAlreadyExistException(string? entityName, object? entity = null) : this(entityName, null, entity, null, null) { }
- public EntityAlreadyExistException(Type? entityType, object? entity = null) : this(null, entityType, entity, null, null) { }
- public EntityAlreadyExistException(string? entityName, Type? entityType, object? entity = null, string? message = null, Exception? inner = null) : base(MakeMessage(entityName, entityType, message), inner)
- {
- _entityName = entityName;
- EntityType = entityType;
- Entity = entity;
- }
-
- private static string MakeMessage(string? entityName, Type? entityType, string? message)
- {
- string? name = entityName ?? (entityType?.Name);
-
- var result = new StringBuilder();
-
- if (name == null)
- result.Append(Resources.Services.Exceptions.EntityAlreadyExistErrorDefault);
- else
- result.AppendFormat(CultureInfo.InvariantCulture, Resources.Services.Exceptions.EntityAlreadyExistError, name);
-
- if (message != null)
- {
- result.Append(' ');
- result.Append(message);
- }
-
- return result.ToString();
- }
-
- protected EntityAlreadyExistException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
-
- public string? EntityName => _entityName ?? (EntityType?.Name);
-
- public Type? EntityType { get; }
-
- public object? Entity { get; }
- }
-}
diff --git a/BackEnd/Timeline/Services/Exceptions/EntityNotExistError.cs b/BackEnd/Timeline/Services/Exceptions/EntityNotExistError.cs deleted file mode 100644 index e79496d3..00000000 --- a/BackEnd/Timeline/Services/Exceptions/EntityNotExistError.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System;
-using System.Globalization;
-using System.Text;
-
-namespace Timeline.Services.Exceptions
-{
- /// <summary>
- /// Thrown when you want to get an entity that does not exist.
- /// </summary>
- /// <example>
- /// For example, you want to get a timeline with given name but it does not exist.
- /// </example>
- [Serializable]
- public class EntityNotExistException : Exception
- {
- public EntityNotExistException() : this(null, null, null, null) { }
- public EntityNotExistException(string? entityName) : this(entityName, null, null, null) { }
- public EntityNotExistException(Type? entityType) : this(null, entityType, null, null) { }
- public EntityNotExistException(string? entityName, Exception? inner) : this(entityName, null, null, inner) { }
- public EntityNotExistException(Type? entityType, Exception? inner) : this(null, entityType, null, inner) { }
- public EntityNotExistException(string? entityName, Type? entityType, string? message = null, Exception? inner = null) : base(MakeMessage(entityName, entityType, message), inner)
- {
- EntityName = entityName;
- EntityType = entityType;
- }
-
- private static string MakeMessage(string? entityName, Type? entityType, string? message)
- {
- string? name = entityName ?? (entityType?.Name);
-
- var result = new StringBuilder();
-
- if (name == null)
- result.Append(Resources.Services.Exceptions.EntityNotExistErrorDefault);
- else
- result.AppendFormat(CultureInfo.InvariantCulture, Resources.Services.Exceptions.EntityNotExistError, name);
-
- if (message != null)
- {
- result.Append(' ');
- result.Append(message);
- }
-
- return result.ToString();
- }
-
- protected EntityNotExistException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
-
- public string? EntityName { get; }
-
- public Type? EntityType { get; }
- }
-}
diff --git a/BackEnd/Timeline/Services/Exceptions/ExceptionMessageHelper.cs b/BackEnd/Timeline/Services/Exceptions/ExceptionMessageHelper.cs deleted file mode 100644 index be3c42a4..00000000 --- a/BackEnd/Timeline/Services/Exceptions/ExceptionMessageHelper.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Timeline.Services.Exceptions
-{
- public static class ExceptionMessageHelper
- {
- public static string AppendAdditionalMessage(this string origin, string? message)
- {
- if (message == null)
- return origin;
- else
- return origin + " " + message;
- }
- }
-}
diff --git a/BackEnd/Timeline/Services/Exceptions/TimelineNotExistException.cs b/BackEnd/Timeline/Services/Exceptions/TimelineNotExistException.cs deleted file mode 100644 index ef882ffe..00000000 --- a/BackEnd/Timeline/Services/Exceptions/TimelineNotExistException.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System;
-using System.Globalization;
-
-namespace Timeline.Services.Exceptions
-{
- [Serializable]
- public class TimelineNotExistException : EntityNotExistException
- {
- public TimelineNotExistException() : this((long?)null) { }
- public TimelineNotExistException(long? id) : this(id, null) { }
- public TimelineNotExistException(long? id, Exception? inner) : this(id, null, inner) { }
- public TimelineNotExistException(long? id, string? message, Exception? inner) : base(EntityNames.Timeline, null, message, inner) { TimelineId = id; }
-
- public TimelineNotExistException(string? timelineName) : this(timelineName, null) { }
- public TimelineNotExistException(string? timelineName, Exception? inner) : this(timelineName, null, inner) { }
- public TimelineNotExistException(string? timelineName, string? message, Exception? inner = null)
- : base(EntityNames.Timeline, null, string.Format(CultureInfo.InvariantCulture, Resources.Services.Exceptions.TimelineNotExistException, timelineName ?? "").AppendAdditionalMessage(message), inner) { TimelineName = timelineName; }
-
- protected TimelineNotExistException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
-
- public string? TimelineName { get; set; }
- public long? TimelineId { get; set; }
- }
-}
diff --git a/BackEnd/Timeline/Services/Exceptions/ImageException.cs b/BackEnd/Timeline/Services/Imaging/ImageException.cs index 20dd48ae..926ecc0a 100644 --- a/BackEnd/Timeline/Services/Exceptions/ImageException.cs +++ b/BackEnd/Timeline/Services/Imaging/ImageException.cs @@ -1,7 +1,7 @@ using System;
using System.Globalization;
-namespace Timeline.Services.Exceptions
+namespace Timeline.Services.Imaging
{
[Serializable]
public class ImageException : Exception
@@ -30,19 +30,20 @@ namespace Timeline.Services.Exceptions public ImageException(string? message) : this(message, null) { }
public ImageException(string? message, Exception? inner) : this(ErrorReason.Unknown, null, null, null, message, inner) { }
- public ImageException(ErrorReason error, byte[]? data, string? requestType = null, string? realType = null, string? message = null, Exception? inner = null) : base(MakeMessage(error).AppendAdditionalMessage(message), inner) { Error = error; ImageData = data; RequestType = requestType; RealType = realType; }
+ public ImageException(ErrorReason error, byte[]? data, string? requestType, string? realType, Exception? inner) : this(error, data, requestType, realType, null, inner) { }
+ public ImageException(ErrorReason error, byte[]? data, string? requestType = null, string? realType = null, string? message = null, Exception? inner = null) : base(message ?? MakeMessage(error), inner) { Error = error; ImageData = data; RequestType = requestType; RealType = realType; }
protected ImageException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
private static string MakeMessage(ErrorReason? reason) =>
- string.Format(CultureInfo.InvariantCulture, Resources.Services.Exceptions.ImageException, reason switch
+ string.Format(CultureInfo.InvariantCulture, Resource.ExceptionImage, reason switch
{
- ErrorReason.CantDecode => Resources.Services.Exceptions.ImageExceptionCantDecode,
- ErrorReason.UnmatchedFormat => Resources.Services.Exceptions.ImageExceptionUnmatchedFormat,
- ErrorReason.NotSquare => Resources.Services.Exceptions.ImageExceptionBadSize,
- _ => Resources.Services.Exceptions.ImageExceptionUnknownError
+ ErrorReason.CantDecode => Resource.ExceptionImageReasonCantDecode,
+ ErrorReason.UnmatchedFormat => Resource.ExceptionImageReasonUnmatchedFormat,
+ ErrorReason.NotSquare => Resource.ExceptionImageReasonBadSize,
+ _ => Resource.ExceptionImageReasonUnknownError
});
public ErrorReason Error { get; }
diff --git a/BackEnd/Timeline/Services/ImageValidator.cs b/BackEnd/Timeline/Services/Imaging/ImageValidator.cs index 59424a7c..b4ae68dc 100644 --- a/BackEnd/Timeline/Services/ImageValidator.cs +++ b/BackEnd/Timeline/Services/Imaging/ImageValidator.cs @@ -3,9 +3,8 @@ using SixLabors.ImageSharp.Formats; using System;
using System.Linq;
using System.Threading.Tasks;
-using Timeline.Services.Exceptions;
-namespace Timeline.Services
+namespace Timeline.Services.Imaging
{
public interface IImageValidator
{
diff --git a/BackEnd/Timeline/Services/Imaging/Resource.Designer.cs b/BackEnd/Timeline/Services/Imaging/Resource.Designer.cs new file mode 100644 index 00000000..e9218208 --- /dev/null +++ b/BackEnd/Timeline/Services/Imaging/Resource.Designer.cs @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Timeline.Services.Imaging {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resource {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resource() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Timeline.Services.Imaging.Resource", typeof(Resource).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Image is in valid because {0}..
+ /// </summary>
+ internal static string ExceptionImage {
+ get {
+ return ResourceManager.GetString("ExceptionImage", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to image is not of required size.
+ /// </summary>
+ internal static string ExceptionImageReasonBadSize {
+ get {
+ return ResourceManager.GetString("ExceptionImageReasonBadSize", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to failed to decode image, see inner exception.
+ /// </summary>
+ internal static string ExceptionImageReasonCantDecode {
+ get {
+ return ResourceManager.GetString("ExceptionImageReasonCantDecode", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to unknown error.
+ /// </summary>
+ internal static string ExceptionImageReasonUnknownError {
+ get {
+ return ResourceManager.GetString("ExceptionImageReasonUnknownError", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to image's actual mime type is not the specified one.
+ /// </summary>
+ internal static string ExceptionImageReasonUnmatchedFormat {
+ get {
+ return ResourceManager.GetString("ExceptionImageReasonUnmatchedFormat", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Services/Imaging/Resource.resx b/BackEnd/Timeline/Services/Imaging/Resource.resx new file mode 100644 index 00000000..060e2a91 --- /dev/null +++ b/BackEnd/Timeline/Services/Imaging/Resource.resx @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="ExceptionImage" xml:space="preserve">
+ <value>Image is in valid because {0}.</value>
+ </data>
+ <data name="ExceptionImageReasonBadSize" xml:space="preserve">
+ <value>image is not of required size</value>
+ </data>
+ <data name="ExceptionImageReasonCantDecode" xml:space="preserve">
+ <value>failed to decode image, see inner exception</value>
+ </data>
+ <data name="ExceptionImageReasonUnknownError" xml:space="preserve">
+ <value>unknown error</value>
+ </data>
+ <data name="ExceptionImageReasonUnmatchedFormat" xml:space="preserve">
+ <value>image's actual mime type is not the specified one</value>
+ </data>
+</root>
\ No newline at end of file diff --git a/BackEnd/Timeline/Services/Mapper/MapperServiceCollectionExtensions.cs b/BackEnd/Timeline/Services/Mapper/MapperServiceCollectionExtensions.cs new file mode 100644 index 00000000..262b2f20 --- /dev/null +++ b/BackEnd/Timeline/Services/Mapper/MapperServiceCollectionExtensions.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.DependencyInjection;
+
+namespace Timeline.Services.Mapper
+{
+ public static class MapperServiceCollectionExtensions
+ {
+ public static void AddMappers(this IServiceCollection services)
+ {
+ services.AddScoped<UserMapper, UserMapper>();
+ services.AddScoped<TimelineMapper, TimelineMapper>();
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs b/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs new file mode 100644 index 00000000..5d823a04 --- /dev/null +++ b/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs @@ -0,0 +1,158 @@ +using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Timeline.Controllers;
+using Timeline.Entities;
+using Timeline.Models.Http;
+using Timeline.Services.Api;
+using Timeline.Services.Timeline;
+
+namespace Timeline.Services.Mapper
+{
+ public class TimelineMapper
+ {
+ private readonly DatabaseContext _database;
+ private readonly UserMapper _userMapper;
+ private readonly IHighlightTimelineService _highlightTimelineService;
+ private readonly IBookmarkTimelineService _bookmarkTimelineService;
+ private readonly ITimelineService _timelineService;
+ private readonly ITimelinePostService _timelinePostService;
+
+ public TimelineMapper(DatabaseContext database, UserMapper userMapper, IHighlightTimelineService highlightTimelineService, IBookmarkTimelineService bookmarkTimelineService, ITimelineService timelineService, ITimelinePostService timelinePostService)
+ {
+ _database = database;
+ _userMapper = userMapper;
+ _highlightTimelineService = highlightTimelineService;
+ _bookmarkTimelineService = bookmarkTimelineService;
+ _timelineService = timelineService;
+ _timelinePostService = timelinePostService;
+ }
+
+ public async Task<HttpTimeline> MapToHttp(TimelineEntity entity, IUrlHelper urlHelper, long? userId, bool isAdministrator)
+ {
+ await _database.Entry(entity).Reference(e => e.Owner).LoadAsync();
+ await _database.Entry(entity).Collection(e => e.Members).Query().Include(m => m.User).LoadAsync();
+
+ var timelineName = entity.Name is null ? "@" + entity.Owner.Username : entity.Name;
+
+ bool manageable;
+
+ if (userId is null)
+ {
+ manageable = false;
+ }
+ else if (isAdministrator)
+ {
+ manageable = true;
+ }
+ else
+ {
+ manageable = await _timelineService.HasManagePermission(entity.Id, userId.Value);
+ }
+
+ bool postable;
+ if (userId is null)
+ {
+ postable = false;
+ }
+ else
+ {
+ postable = await _timelineService.IsMemberOf(entity.Id, userId.Value);
+ }
+
+ return new HttpTimeline(
+ uniqueId: entity.UniqueId,
+ title: string.IsNullOrEmpty(entity.Title) ? timelineName : entity.Title,
+ name: timelineName,
+ nameLastModifed: entity.NameLastModified,
+ description: entity.Description ?? "",
+ 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),
+ isBookmark: userId is not null && await _bookmarkTimelineService.IsBookmark(userId.Value, entity.Id, false, false),
+ manageable: manageable,
+ postable: postable,
+ links: new HttpTimelineLinks(
+ self: urlHelper.ActionLink(nameof(TimelineController.TimelineGet), nameof(TimelineController)[0..^nameof(Controller).Length], new { timeline = timelineName }),
+ posts: urlHelper.ActionLink(nameof(TimelinePostController.List), nameof(TimelinePostController)[0..^nameof(Controller).Length], new { timeline = timelineName })
+ )
+ );
+ }
+
+ public async Task<List<HttpTimeline>> MapToHttp(List<TimelineEntity> entities, IUrlHelper urlHelper, long? userId, bool isAdministrator)
+ {
+ var result = new List<HttpTimeline>();
+ foreach (var entity in entities)
+ {
+ result.Add(await MapToHttp(entity, urlHelper, userId, isAdministrator));
+ }
+ return result;
+ }
+
+
+ public async Task<HttpTimelinePost> MapToHttp(TimelinePostEntity entity, string timelineName, IUrlHelper urlHelper, long? userId, bool isAdministrator)
+ {
+ _ = timelineName;
+
+ await _database.Entry(entity).Collection(p => p.DataList).LoadAsync();
+ await _database.Entry(entity).Reference(e => e.Author).LoadAsync();
+
+ List<HttpTimelinePostDataDigest> dataDigestList = entity.DataList.OrderBy(d => d.Index).Select(d => new HttpTimelinePostDataDigest(d.Kind, $"\"{d.DataTag}\"", d.LastUpdated)).ToList();
+
+ HttpUser? author = null;
+ if (entity.Author is not null)
+ {
+ author = await _userMapper.MapToHttp(entity.Author, urlHelper);
+ }
+
+ bool editable;
+
+ if (userId is null)
+ {
+ editable = false;
+ }
+ else if (isAdministrator)
+ {
+ editable = true;
+ }
+ else
+ {
+ editable = await _timelinePostService.HasPostModifyPermission(entity.TimelineId, entity.LocalId, userId.Value);
+ }
+
+
+ return new HttpTimelinePost(
+ id: entity.LocalId,
+ dataList: dataDigestList,
+ time: entity.Time,
+ author: author,
+ color: entity.Color,
+ deleted: entity.Deleted,
+ lastUpdated: entity.LastUpdated,
+ timelineName: timelineName,
+ editable: editable
+ );
+ }
+
+ public async Task<List<HttpTimelinePost>> MapToHttp(List<TimelinePostEntity> entities, string timelineName, IUrlHelper urlHelper, long? userId, bool isAdministrator)
+ {
+ var result = new List<HttpTimelinePost>();
+ foreach (var entity in entities)
+ {
+ result.Add(await MapToHttp(entity, timelineName, urlHelper, userId, isAdministrator));
+ }
+ return result;
+ }
+
+ internal Task MapToHttp(TimelinePostEntity post, string timeline, IUrlHelper url)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Services/Mapper/UserMapper.cs b/BackEnd/Timeline/Services/Mapper/UserMapper.cs new file mode 100644 index 00000000..42f88d8a --- /dev/null +++ b/BackEnd/Timeline/Services/Mapper/UserMapper.cs @@ -0,0 +1,47 @@ +using Microsoft.AspNetCore.Mvc;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Timeline.Controllers;
+using Timeline.Entities;
+using Timeline.Models.Http;
+using Timeline.Services.User;
+
+namespace Timeline.Services.Mapper
+{
+ public class UserMapper
+ {
+ private readonly DatabaseContext _database;
+ private readonly IUserPermissionService _userPermissionService;
+
+ public UserMapper(DatabaseContext database, IUserPermissionService userPermissionService)
+ {
+ _database = database;
+ _userPermissionService = userPermissionService;
+ }
+
+ public async Task<HttpUser> MapToHttp(UserEntity entity, IUrlHelper urlHelper)
+ {
+ return new HttpUser(
+ uniqueId: entity.UniqueId,
+ username: entity.Username,
+ nickname: string.IsNullOrEmpty(entity.Nickname) ? entity.Username : entity.Nickname,
+ permissions: (await _userPermissionService.GetPermissionsOfUserAsync(entity.Id, false)).ToStringList(),
+ links: new HttpUserLinks(
+ self: urlHelper.ActionLink(nameof(UserController.Get), nameof(UserController)[0..^nameof(Controller).Length], new { entity.Username }),
+ avatar: urlHelper.ActionLink(nameof(UserAvatarController.Get), nameof(UserAvatarController)[0..^nameof(Controller).Length], new { entity.Username }),
+ timeline: urlHelper.ActionLink(nameof(TimelineController.TimelineGet), nameof(TimelineController)[0..^nameof(Controller).Length], new { timeline = "@" + entity.Username })
+ )
+ );
+ }
+
+ public async Task<List<HttpUser>> MapToHttp(List<UserEntity> entities, IUrlHelper urlHelper)
+ {
+ var result = new List<HttpUser>();
+ foreach (var entity in entities)
+ {
+ result.Add(await MapToHttp(entity, urlHelper));
+ }
+ return result;
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Services/Resource.Designer.cs b/BackEnd/Timeline/Services/Resource.Designer.cs new file mode 100644 index 00000000..def89b4f --- /dev/null +++ b/BackEnd/Timeline/Services/Resource.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Timeline.Services {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resource {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resource() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Timeline.Services.Resource", typeof(Resource).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to A entity with given constraints already exists..
+ /// </summary>
+ internal static string ExceptionEntityAlreadyExist {
+ get {
+ return ResourceManager.GetString("ExceptionEntityAlreadyExist", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Requested entity does not exist..
+ /// </summary>
+ internal static string ExceptionEntityNotExist {
+ get {
+ return ResourceManager.GetString("ExceptionEntityNotExist", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Services/Resource.resx b/BackEnd/Timeline/Services/Resource.resx new file mode 100644 index 00000000..526a2c29 --- /dev/null +++ b/BackEnd/Timeline/Services/Resource.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="ExceptionEntityAlreadyExist" xml:space="preserve">
+ <value>A entity with given constraints already exists.</value>
+ </data>
+ <data name="ExceptionEntityNotExist" xml:space="preserve">
+ <value>Requested entity does not exist.</value>
+ </data>
+</root>
\ No newline at end of file diff --git a/BackEnd/Timeline/Services/BasicTimelineService.cs b/BackEnd/Timeline/Services/Timeline/BasicTimelineService.cs index be500135..f917b176 100644 --- a/BackEnd/Timeline/Services/BasicTimelineService.cs +++ b/BackEnd/Timeline/Services/Timeline/BasicTimelineService.cs @@ -6,9 +6,9 @@ using System.Threading.Tasks; using Timeline.Entities;
using Timeline.Models;
using Timeline.Models.Validation;
-using Timeline.Services.Exceptions;
+using Timeline.Services.User;
-namespace Timeline.Services
+namespace Timeline.Services.Timeline
{
/// <summary>
/// This service provide some basic timeline functions, which should be used internally for other services.
diff --git a/BackEnd/Timeline/Services/MarkdownProcessor.cs b/BackEnd/Timeline/Services/Timeline/MarkdownProcessor.cs index f34432cd..d338ba5e 100644 --- a/BackEnd/Timeline/Services/MarkdownProcessor.cs +++ b/BackEnd/Timeline/Services/Timeline/MarkdownProcessor.cs @@ -1,15 +1,15 @@ -using System;
-using System.IO;
-using System.Linq;
-using System.Text;
using Markdig;
using Markdig.Renderers.Normalize;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
using Microsoft.AspNetCore.Mvc;
+using System;
+using System.IO;
+using System.Linq;
+using System.Text;
using Timeline.Controllers;
-namespace Timeline.Services
+namespace Timeline.Services.Timeline
{
public class MarkdownProcessor
{
diff --git a/BackEnd/Timeline/Services/Timeline/Resource.Designer.cs b/BackEnd/Timeline/Services/Timeline/Resource.Designer.cs new file mode 100644 index 00000000..31fd6320 --- /dev/null +++ b/BackEnd/Timeline/Services/Timeline/Resource.Designer.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Timeline.Services.Timeline {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resource {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resource() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Timeline.Services.Timeline.Resource", typeof(Resource).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Timeline with given constraints already exist..
+ /// </summary>
+ internal static string ExceptionTimelineAlreadyExist {
+ get {
+ return ResourceManager.GetString("ExceptionTimelineAlreadyExist", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Timeline name is of bad format. {0}.
+ /// </summary>
+ internal static string ExceptionTimelineNameBadFormat {
+ get {
+ return ResourceManager.GetString("ExceptionTimelineNameBadFormat", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Requested timeline does not exist..
+ /// </summary>
+ internal static string ExceptionTimelineNotExist {
+ get {
+ return ResourceManager.GetString("ExceptionTimelineNotExist", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Requested timeline post does not exist because {0}..
+ /// </summary>
+ internal static string ExceptionTimelinePostNoExist {
+ get {
+ return ResourceManager.GetString("ExceptionTimelinePostNoExist", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to it is deleted.
+ /// </summary>
+ internal static string ExceptionTimelinePostNoExistReasonDeleted {
+ get {
+ return ResourceManager.GetString("ExceptionTimelinePostNoExistReasonDeleted", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to it has not been created.
+ /// </summary>
+ internal static string ExceptionTimelinePostNoExistReasonNotCreated {
+ get {
+ return ResourceManager.GetString("ExceptionTimelinePostNoExistReasonNotCreated", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Services/Timeline/Resource.resx b/BackEnd/Timeline/Services/Timeline/Resource.resx new file mode 100644 index 00000000..7fd7b5c7 --- /dev/null +++ b/BackEnd/Timeline/Services/Timeline/Resource.resx @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="ExceptionTimelineAlreadyExist" xml:space="preserve">
+ <value>Timeline with given constraints already exist.</value>
+ </data>
+ <data name="ExceptionTimelineNameBadFormat" xml:space="preserve">
+ <value>Timeline name is of bad format. {0}</value>
+ </data>
+ <data name="ExceptionTimelineNotExist" xml:space="preserve">
+ <value>Requested timeline does not exist.</value>
+ </data>
+ <data name="ExceptionTimelinePostNoExist" xml:space="preserve">
+ <value>Requested timeline post does not exist because {0}.</value>
+ </data>
+ <data name="ExceptionTimelinePostNoExistReasonDeleted" xml:space="preserve">
+ <value>it is deleted</value>
+ </data>
+ <data name="ExceptionTimelinePostNoExistReasonNotCreated" xml:space="preserve">
+ <value>it has not been created</value>
+ </data>
+</root>
\ No newline at end of file diff --git a/BackEnd/Timeline/Services/Timeline/TimelineAlreadyExistException.cs b/BackEnd/Timeline/Services/Timeline/TimelineAlreadyExistException.cs new file mode 100644 index 00000000..11fc4ef8 --- /dev/null +++ b/BackEnd/Timeline/Services/Timeline/TimelineAlreadyExistException.cs @@ -0,0 +1,24 @@ +using System;
+
+namespace Timeline.Services.Timeline
+{
+ /// <summary>
+ /// The user requested does not exist.
+ /// </summary>
+ [Serializable]
+ public class TimelineAlreadyExistException : EntityAlreadyExistException
+ {
+ public TimelineAlreadyExistException() : this(null, null, null) { }
+ public TimelineAlreadyExistException(object? entity) : this(entity, null, null) { }
+ public TimelineAlreadyExistException(object? entity, Exception? inner) : this(entity, null, inner) { }
+ public TimelineAlreadyExistException(object? entity, string? message, Exception? inner)
+ : base(EntityNames.Timeline, entity, message ?? Resource.ExceptionTimelineAlreadyExist, inner)
+ {
+
+ }
+
+ protected TimelineAlreadyExistException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+}
diff --git a/BackEnd/Timeline/Services/Timeline/TimelineNotExistException.cs b/BackEnd/Timeline/Services/Timeline/TimelineNotExistException.cs new file mode 100644 index 00000000..2cfbdedf --- /dev/null +++ b/BackEnd/Timeline/Services/Timeline/TimelineNotExistException.cs @@ -0,0 +1,27 @@ +using System;
+
+namespace Timeline.Services.Timeline
+{
+ [Serializable]
+ public class TimelineNotExistException : EntityNotExistException
+ {
+ public TimelineNotExistException() : this(null, null, null, null) { }
+ public TimelineNotExistException(long? id) : this(null, id, null, null) { }
+ public TimelineNotExistException(long? id, Exception? inner) : this(null, id, null, inner) { }
+ public TimelineNotExistException(string? timelineName) : this(timelineName, null, null, null) { }
+ public TimelineNotExistException(string? timelineName, Exception? inner) : this(timelineName, null, null, inner) { }
+ public TimelineNotExistException(string? timelineName, long? timelineId, string? message, Exception? inner = null)
+ : base(EntityNames.Timeline, message ?? Resource.ExceptionTimelineNotExist, inner)
+ {
+ TimelineId = timelineId;
+ TimelineName = timelineName;
+ }
+
+ protected TimelineNotExistException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+
+ public string? TimelineName { get; set; }
+ public long? TimelineId { get; set; }
+ }
+}
diff --git a/BackEnd/Timeline/Services/TimelinePostCreateDataException.cs b/BackEnd/Timeline/Services/Timeline/TimelinePostCreateDataException.cs index 10a09de7..669e8bc9 100644 --- a/BackEnd/Timeline/Services/TimelinePostCreateDataException.cs +++ b/BackEnd/Timeline/Services/Timeline/TimelinePostCreateDataException.cs @@ -1,4 +1,4 @@ -namespace Timeline.Services
+namespace Timeline.Services.Timeline
{
[System.Serializable]
public class TimelinePostCreateDataException : System.Exception
diff --git a/BackEnd/Timeline/Services/TimelinePostDataNotExistException.cs b/BackEnd/Timeline/Services/Timeline/TimelinePostDataNotExistException.cs index c70f5d9c..177973a3 100644 --- a/BackEnd/Timeline/Services/TimelinePostDataNotExistException.cs +++ b/BackEnd/Timeline/Services/Timeline/TimelinePostDataNotExistException.cs @@ -1,6 +1,6 @@ using System;
-namespace Timeline.Services
+namespace Timeline.Services.Timeline
{
[Serializable]
public class TimelinePostDataNotExistException : Exception
diff --git a/BackEnd/Timeline/Services/Exceptions/TimelinePostNotExistException.cs b/BackEnd/Timeline/Services/Timeline/TimelinePostNotExistException.cs index 2a7b5b28..e0e819aa 100644 --- a/BackEnd/Timeline/Services/Exceptions/TimelinePostNotExistException.cs +++ b/BackEnd/Timeline/Services/Timeline/TimelinePostNotExistException.cs @@ -1,30 +1,28 @@ using System;
using System.Globalization;
-namespace Timeline.Services.Exceptions
+namespace Timeline.Services.Timeline
{
[Serializable]
public class TimelinePostNotExistException : EntityNotExistException
{
public TimelinePostNotExistException() : this(null, null, false, null, null) { }
- [Obsolete("This has no meaning.")]
public TimelinePostNotExistException(string? message) : this(message, null) { }
- [Obsolete("This has no meaning.")]
public TimelinePostNotExistException(string? message, Exception? inner) : this(null, null, false, message, inner) { }
protected TimelinePostNotExistException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
public TimelinePostNotExistException(long? timelineId, long? postId, bool isDelete, string? message = null, Exception? inner = null)
- : base(EntityNames.TimelinePost, null, MakeMessage(timelineId, postId, isDelete).AppendAdditionalMessage(message), inner)
+ : base(EntityNames.TimelinePost, message ?? MakeMessage(isDelete), inner)
{
TimelineId = timelineId;
PostId = postId;
IsDelete = isDelete;
}
- private static string MakeMessage(long? timelineId, long? postId, bool isDelete)
+ private static string MakeMessage(bool isDelete)
{
- return string.Format(CultureInfo.InvariantCulture, isDelete ? Resources.Services.Exceptions.TimelinePostNotExistExceptionDeleted : Resources.Services.Exceptions.TimelinePostNotExistException, timelineId, postId);
+ return string.Format(CultureInfo.InvariantCulture, Resource.ExceptionTimelinePostNoExist, isDelete ? Resource.ExceptionTimelinePostNoExistReasonDeleted : Resource.ExceptionTimelinePostNoExistReasonNotCreated);
}
public long? TimelineId { get; set; }
diff --git a/BackEnd/Timeline/Services/TimelinePostService.cs b/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs index f64c4c22..073fffdf 100644 --- a/BackEnd/Timeline/Services/TimelinePostService.cs +++ b/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs @@ -10,9 +10,11 @@ using Timeline.Helpers; using Timeline.Helpers.Cache;
using Timeline.Models;
using Timeline.Models.Validation;
-using Timeline.Services.Exceptions;
+using Timeline.Services.Data;
+using Timeline.Services.Imaging;
+using Timeline.Services.User;
-namespace Timeline.Services
+namespace Timeline.Services.Timeline
{
public class TimelinePostCreateRequestData
{
diff --git a/BackEnd/Timeline/Services/TimelineService.cs b/BackEnd/Timeline/Services/Timeline/TimelineService.cs index bed1c99b..342ce234 100644 --- a/BackEnd/Timeline/Services/TimelineService.cs +++ b/BackEnd/Timeline/Services/Timeline/TimelineService.cs @@ -6,10 +6,9 @@ using System.Threading.Tasks; using Timeline.Entities;
using Timeline.Models;
using Timeline.Models.Validation;
-using Timeline.Services.Exceptions;
-using static Timeline.Resources.Services.TimelineService;
+using Timeline.Services.User;
-namespace Timeline.Services
+namespace Timeline.Services.Timeline
{
public static class TimelineHelper
{
@@ -193,7 +192,7 @@ namespace Timeline.Services {
if (!_timelineNameValidator.Validate(name, out var message))
{
- throw new ArgumentException(ExceptionTimelineNameBadFormat.AppendAdditionalMessage(message), paramName);
+ throw new ArgumentException(string.Format(Resource.ExceptionTimelineNameBadFormat, message), paramName);
}
}
@@ -237,7 +236,7 @@ namespace Timeline.Services var conflict = await _database.Timelines.AnyAsync(t => t.Name == newProperties.Name);
if (conflict)
- throw new EntityAlreadyExistException(EntityNames.Timeline, null, ExceptionTimelineNameConflict);
+ throw new TimelineAlreadyExistException();
entity.Name = newProperties.Name;
@@ -416,7 +415,7 @@ namespace Timeline.Services var conflict = await _database.Timelines.AnyAsync(t => t.Name == name);
if (conflict)
- throw new EntityAlreadyExistException(EntityNames.Timeline, null, ExceptionTimelineNameConflict);
+ throw new TimelineAlreadyExistException();
var entity = CreateNewTimelineEntity(name, owner);
diff --git a/BackEnd/Timeline/Services/Token/UserTokenManager.cs b/BackEnd/Timeline/Services/Token/UserTokenManager.cs index 00bc2cf7..4a5f08d2 100644 --- a/BackEnd/Timeline/Services/Token/UserTokenManager.cs +++ b/BackEnd/Timeline/Services/Token/UserTokenManager.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Timeline.Configs;
using Timeline.Entities;
using Timeline.Helpers;
-using Timeline.Services.Exceptions;
+using Timeline.Services.User;
namespace Timeline.Services.Token
{
diff --git a/BackEnd/Timeline/Services/BadPasswordException.cs b/BackEnd/Timeline/Services/User/BadPasswordException.cs index f609371d..7302fbca 100644 --- a/BackEnd/Timeline/Services/BadPasswordException.cs +++ b/BackEnd/Timeline/Services/User/BadPasswordException.cs @@ -1,16 +1,14 @@ using System;
-using Timeline.Helpers;
-namespace Timeline.Services
+namespace Timeline.Services.User
{
[Serializable]
public class BadPasswordException : Exception
{
- public BadPasswordException() : base(Resources.Services.Exception.BadPasswordException) { }
- public BadPasswordException(string message, Exception inner) : base(message, inner) { }
-
- public BadPasswordException(string badPassword)
- : base(Log.Format(Resources.Services.Exception.BadPasswordException, ("Bad Password", badPassword)))
+ public BadPasswordException() : this(null, null, null) { }
+ public BadPasswordException(string? badPassword) : this(badPassword, null, null) { }
+ public BadPasswordException(string? badPassword, Exception? inner) : this(badPassword, null, inner) { }
+ public BadPasswordException(string? badPassword, string? message, Exception? inner) : base(message ?? Resource.ExceptionBadPassword, inner)
{
Password = badPassword;
}
diff --git a/BackEnd/Timeline/Services/BasicUserService.cs b/BackEnd/Timeline/Services/User/BasicUserService.cs index de0829ee..a3763ef6 100644 --- a/BackEnd/Timeline/Services/BasicUserService.cs +++ b/BackEnd/Timeline/Services/User/BasicUserService.cs @@ -4,9 +4,8 @@ using System.Linq; using System.Threading.Tasks;
using Timeline.Entities;
using Timeline.Models.Validation;
-using Timeline.Services.Exceptions;
-namespace Timeline.Services
+namespace Timeline.Services.User
{
/// <summary>
/// This service provide some basic user features, which should be used internally for other services.
diff --git a/BackEnd/Timeline/Services/Exceptions/InvalidOperationOnRootUserException.cs b/BackEnd/Timeline/Services/User/InvalidOperationOnRootUserException.cs index 2bcab316..c432febd 100644 --- a/BackEnd/Timeline/Services/Exceptions/InvalidOperationOnRootUserException.cs +++ b/BackEnd/Timeline/Services/User/InvalidOperationOnRootUserException.cs @@ -1,6 +1,6 @@ using System;
-namespace Timeline.Services.Exceptions
+namespace Timeline.Services.User
{
[Serializable]
diff --git a/BackEnd/Timeline/Services/PasswordBadFormatException.cs b/BackEnd/Timeline/Services/User/PasswordBadFormatException.cs index 2029ebb4..b9d76017 100644 --- a/BackEnd/Timeline/Services/PasswordBadFormatException.cs +++ b/BackEnd/Timeline/Services/User/PasswordBadFormatException.cs @@ -1,8 +1,7 @@ using System;
-namespace Timeline.Services
+namespace Timeline.Services.User
{
-
[Serializable]
public class PasswordBadFormatException : Exception
{
diff --git a/BackEnd/Timeline/Services/PasswordService.cs b/BackEnd/Timeline/Services/User/PasswordService.cs index 8114a520..580471e1 100644 --- a/BackEnd/Timeline/Services/PasswordService.cs +++ b/BackEnd/Timeline/Services/User/PasswordService.cs @@ -3,7 +3,7 @@ using System; using System.Runtime.CompilerServices;
using System.Security.Cryptography;
-namespace Timeline.Services
+namespace Timeline.Services.User
{
/// <summary>
/// Hashed password is of bad format.
diff --git a/BackEnd/Timeline/Services/User/Resource.Designer.cs b/BackEnd/Timeline/Services/User/Resource.Designer.cs new file mode 100644 index 00000000..d64a7aab --- /dev/null +++ b/BackEnd/Timeline/Services/User/Resource.Designer.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Timeline.Services.User {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resource {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resource() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Timeline.Services.User.Resource", typeof(Resource).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Password is wrong..
+ /// </summary>
+ internal static string ExceptionBadPassword {
+ get {
+ return ResourceManager.GetString("ExceptionBadPassword", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Nickname is of bad format. {0}.
+ /// </summary>
+ internal static string ExceptionNicknameBadFormat {
+ get {
+ return ResourceManager.GetString("ExceptionNicknameBadFormat", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Password can't be empty..
+ /// </summary>
+ internal static string ExceptionPasswordEmpty {
+ get {
+ return ResourceManager.GetString("ExceptionPasswordEmpty", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to User with given constraints already exists..
+ /// </summary>
+ internal static string ExceptionUserAlreadyExist {
+ get {
+ return ResourceManager.GetString("ExceptionUserAlreadyExist", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Username is of bad format. {0}.
+ /// </summary>
+ internal static string ExceptionUsernameBadFormat {
+ get {
+ return ResourceManager.GetString("ExceptionUsernameBadFormat", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Requested user does not exist..
+ /// </summary>
+ internal static string ExceptionUserNotExist {
+ get {
+ return ResourceManager.GetString("ExceptionUserNotExist", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Services/User/Resource.resx b/BackEnd/Timeline/Services/User/Resource.resx new file mode 100644 index 00000000..732cfefd --- /dev/null +++ b/BackEnd/Timeline/Services/User/Resource.resx @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="ExceptionBadPassword" xml:space="preserve">
+ <value>Password is wrong.</value>
+ </data>
+ <data name="ExceptionNicknameBadFormat" xml:space="preserve">
+ <value>Nickname is of bad format. {0}</value>
+ </data>
+ <data name="ExceptionPasswordEmpty" xml:space="preserve">
+ <value>Password can't be empty.</value>
+ </data>
+ <data name="ExceptionUserAlreadyExist" xml:space="preserve">
+ <value>User with given constraints already exists.</value>
+ </data>
+ <data name="ExceptionUsernameBadFormat" xml:space="preserve">
+ <value>Username is of bad format. {0}</value>
+ </data>
+ <data name="ExceptionUserNotExist" xml:space="preserve">
+ <value>Requested user does not exist.</value>
+ </data>
+</root>
\ No newline at end of file diff --git a/BackEnd/Timeline/Services/User/UserAlreadyExistException.cs b/BackEnd/Timeline/Services/User/UserAlreadyExistException.cs new file mode 100644 index 00000000..e257af74 --- /dev/null +++ b/BackEnd/Timeline/Services/User/UserAlreadyExistException.cs @@ -0,0 +1,24 @@ +using System;
+
+namespace Timeline.Services.User
+{
+ /// <summary>
+ /// The user requested does not exist.
+ /// </summary>
+ [Serializable]
+ public class UserAlreadyExistException : EntityAlreadyExistException
+ {
+ public UserAlreadyExistException() : this(null, null, null) { }
+ public UserAlreadyExistException(object? entity) : this(entity, null, null) { }
+ public UserAlreadyExistException(object? entity, Exception? inner) : this(entity, null, inner) { }
+ public UserAlreadyExistException(object? entity, string? message, Exception? inner)
+ : base(EntityNames.User, entity, message ?? Resource.ExceptionUserAlreadyExist, inner)
+ {
+
+ }
+
+ protected UserAlreadyExistException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+}
diff --git a/BackEnd/Timeline/Services/UserAvatarService.cs b/BackEnd/Timeline/Services/User/UserAvatarService.cs index 5a6d013e..0a4b7438 100644 --- a/BackEnd/Timeline/Services/UserAvatarService.cs +++ b/BackEnd/Timeline/Services/User/UserAvatarService.cs @@ -10,9 +10,10 @@ using System.Threading.Tasks; using Timeline.Entities;
using Timeline.Helpers.Cache;
using Timeline.Models;
-using Timeline.Services.Exceptions;
+using Timeline.Services.Data;
+using Timeline.Services.Imaging;
-namespace Timeline.Services
+namespace Timeline.Services.User
{
/// <summary>
/// Provider for default user avatar.
diff --git a/BackEnd/Timeline/Services/UserCredentialService.cs b/BackEnd/Timeline/Services/User/UserCredentialService.cs index 8aeef9ef..6becc469 100644 --- a/BackEnd/Timeline/Services/UserCredentialService.cs +++ b/BackEnd/Timeline/Services/User/UserCredentialService.cs @@ -6,9 +6,8 @@ using System.Threading.Tasks; using Timeline.Entities;
using Timeline.Helpers;
using Timeline.Models.Validation;
-using Timeline.Services.Exceptions;
-namespace Timeline.Services
+namespace Timeline.Services.User
{
public interface IUserCredentialService
{
diff --git a/BackEnd/Timeline/Services/UserDeleteService.cs b/BackEnd/Timeline/Services/User/UserDeleteService.cs index a4e77abc..8da4678a 100644 --- a/BackEnd/Timeline/Services/UserDeleteService.cs +++ b/BackEnd/Timeline/Services/User/UserDeleteService.cs @@ -5,12 +5,10 @@ using System.Globalization; using System.Linq;
using System.Threading.Tasks;
using Timeline.Entities;
-using Timeline.Helpers;
using Timeline.Models.Validation;
-using Timeline.Services.Exceptions;
-using static Timeline.Resources.Services.UserService;
+using Timeline.Services.Timeline;
-namespace Timeline.Services
+namespace Timeline.Services.User
{
public interface IUserDeleteService
{
@@ -49,7 +47,7 @@ namespace Timeline.Services if (!_usernameValidator.Validate(username, out var message))
{
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExceptionUsernameBadFormat, message), nameof(username));
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resource.ExceptionUsernameBadFormat, message), nameof(username));
}
var user = await _databaseContext.Users.Where(u => u.Username == username).SingleOrDefaultAsync();
@@ -64,7 +62,6 @@ namespace Timeline.Services _databaseContext.Users.Remove(user);
await _databaseContext.SaveChangesAsync();
- _logger.LogInformation(Log.Format(LogDatabaseRemove, ("Id", user.Id), ("Username", user.Username)));
return true;
}
diff --git a/BackEnd/Timeline/Services/Exceptions/UserNotExistException.cs b/BackEnd/Timeline/Services/User/UserNotExistException.cs index 7ef714df..bc5d8d9e 100644 --- a/BackEnd/Timeline/Services/Exceptions/UserNotExistException.cs +++ b/BackEnd/Timeline/Services/User/UserNotExistException.cs @@ -1,7 +1,6 @@ using System;
-using System.Globalization;
-namespace Timeline.Services.Exceptions
+namespace Timeline.Services.User
{
/// <summary>
/// The user requested does not exist.
@@ -10,14 +9,12 @@ namespace Timeline.Services.Exceptions public class UserNotExistException : EntityNotExistException
{
public UserNotExistException() : this(null, null, null, null) { }
- public UserNotExistException(string? username, Exception? inner) : this(username, null, null, inner) { }
-
public UserNotExistException(string? username) : this(username, null, null, null) { }
-
+ public UserNotExistException(string? username, Exception? inner) : this(username, null, null, inner) { }
public UserNotExistException(long id) : this(null, id, null, null) { }
-
- public UserNotExistException(string? username, long? id, string? message, Exception? inner) : base(EntityNames.User, null,
- string.Format(CultureInfo.InvariantCulture, Resources.Services.Exceptions.UserNotExistException, username ?? "", id).AppendAdditionalMessage(message), inner)
+ public UserNotExistException(long id, Exception? inner) : this(null, id, null, inner) { }
+ public UserNotExistException(string? username, long? id, string? message, Exception? inner)
+ : base(EntityNames.User, message ?? Resource.ExceptionUserNotExist, inner)
{
Username = username;
Id = id;
diff --git a/BackEnd/Timeline/Services/UserPermissionService.cs b/BackEnd/Timeline/Services/User/UserPermissionService.cs index bd7cd6aa..f292142d 100644 --- a/BackEnd/Timeline/Services/UserPermissionService.cs +++ b/BackEnd/Timeline/Services/User/UserPermissionService.cs @@ -5,9 +5,8 @@ using System.Collections.Generic; using System.Linq;
using System.Threading.Tasks;
using Timeline.Entities;
-using Timeline.Services.Exceptions;
-namespace Timeline.Services
+namespace Timeline.Services.User
{
public enum UserPermission
{
diff --git a/BackEnd/Timeline/Services/UserService.cs b/BackEnd/Timeline/Services/User/UserService.cs index 288d208c..bbbe15b0 100644 --- a/BackEnd/Timeline/Services/UserService.cs +++ b/BackEnd/Timeline/Services/User/UserService.cs @@ -6,12 +6,9 @@ using System.Globalization; using System.Linq;
using System.Threading.Tasks;
using Timeline.Entities;
-using Timeline.Helpers;
using Timeline.Models.Validation;
-using Timeline.Services.Exceptions;
-using static Timeline.Resources.Services.UserService;
-namespace Timeline.Services
+namespace Timeline.Services.User
{
/// <summary>
/// Null means not change.
@@ -88,7 +85,7 @@ namespace Timeline.Services {
if (!_usernameValidator.Validate(username, out var message))
{
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExceptionUsernameBadFormat, message), paramName);
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resource.ExceptionUsernameBadFormat, message), paramName);
}
}
@@ -96,7 +93,7 @@ namespace Timeline.Services {
if (password.Length == 0)
{
- throw new ArgumentException(ExceptionPasswordEmpty, paramName);
+ throw new ArgumentException(Resource.ExceptionPasswordEmpty, paramName);
}
}
@@ -104,13 +101,13 @@ namespace Timeline.Services {
if (!_nicknameValidator.Validate(nickname, out var message))
{
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExceptionNicknameBadFormat, message), paramName);
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resource.ExceptionNicknameBadFormat, message), paramName);
}
}
- private static void ThrowUsernameConflict()
+ private static void ThrowUsernameConflict(object? user)
{
- throw new EntityAlreadyExistException(EntityNames.User, ExceptionUsernameConflict);
+ throw new UserAlreadyExistException(user);
}
public async Task<UserEntity> GetUser(long id)
@@ -140,7 +137,7 @@ namespace Timeline.Services var conflict = await _databaseContext.Users.AnyAsync(u => u.Username == username);
if (conflict)
- ThrowUsernameConflict();
+ ThrowUsernameConflict(null);
var newEntity = new UserEntity
{
@@ -151,8 +148,6 @@ namespace Timeline.Services _databaseContext.Users.Add(newEntity);
await _databaseContext.SaveChangesAsync();
- _logger.LogInformation(Log.Format(LogDatabaseCreate, ("Id", newEntity.Id), ("Username", username)));
-
return newEntity;
}
@@ -184,7 +179,7 @@ namespace Timeline.Services {
var conflict = await _databaseContext.Users.AnyAsync(u => u.Username == username);
if (conflict)
- ThrowUsernameConflict();
+ ThrowUsernameConflict(null);
entity.Username = username;
entity.UsernameChangeTime = now;
@@ -211,7 +206,6 @@ namespace Timeline.Services }
await _databaseContext.SaveChangesAsync();
- _logger.LogInformation(LogDatabaseUpdate, ("Id", id));
}
return entity;
|