From 8ec442d1bec9e379d769a2d6f9c657734f16c156 Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 16 Aug 2021 10:11:24 +0200 Subject: [PATCH 01/10] docs: add `README.md` files to explain directory structure --- Messenger/Messenger.Core.Tests.MSTest/README.md | 1 + Messenger/Messenger.Core/Models/Channel.cs | 17 ++++++++++++++++- Messenger/Messenger.Core/README.md | 5 +++++ Messenger/Messenger.Tests.MSTest/README.md | 2 ++ Messenger/README.md | 8 ++++++++ 5 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 Messenger/Messenger.Core.Tests.MSTest/README.md create mode 100644 Messenger/Messenger.Core/README.md create mode 100644 Messenger/Messenger.Tests.MSTest/README.md create mode 100644 Messenger/README.md diff --git a/Messenger/Messenger.Core.Tests.MSTest/README.md b/Messenger/Messenger.Core.Tests.MSTest/README.md new file mode 100644 index 00000000..4f1714b6 --- /dev/null +++ b/Messenger/Messenger.Core.Tests.MSTest/README.md @@ -0,0 +1 @@ +This is the `Messenger.Core.Tests.MSTest` project, it holds the test code for the [Messenger.Core](../Messenger.Core/) project and mirrors it's directory structure. diff --git a/Messenger/Messenger.Core/Models/Channel.cs b/Messenger/Messenger.Core/Models/Channel.cs index 5a14005d..4da736af 100644 --- a/Messenger/Messenger.Core/Models/Channel.cs +++ b/Messenger/Messenger.Core/Models/Channel.cs @@ -1,14 +1,29 @@ - namespace Messenger.Core.Models { + + /// + /// The source code side representation of a team's channel + /// public class Channel { + /// + /// The unique id of the channel + /// public uint ChannelId { get; set; } + /// + /// The name of the channel + /// public string ChannelName { get; set; } + /// + /// The id of the team the channel belongs to + /// public uint TeamId { get; set; } + /// + /// Default initialize all members(string values get initialized to "" instead of null) + /// public Channel() { ChannelName = ""; diff --git a/Messenger/Messenger.Core/README.md b/Messenger/Messenger.Core/README.md new file mode 100644 index 00000000..096825e0 --- /dev/null +++ b/Messenger/Messenger.Core/README.md @@ -0,0 +1,5 @@ +This is the `Messenger.Core` project, it holds the core/backend functionality and data models. + +The [Helpers](Helpers/) directory holds non-essential functionality - like conversion from DB rows to classes - and is used internally by the [Services](Services/) +The [Models](Models/) directory holds essential data models like classes for teams and messages or enums for things like notification types +The [Services](Services/) directory holds the core functionality - like creating teams and messages - for interacting with the external database and blob storage diff --git a/Messenger/Messenger.Tests.MSTest/README.md b/Messenger/Messenger.Tests.MSTest/README.md new file mode 100644 index 00000000..7735bbdd --- /dev/null +++ b/Messenger/Messenger.Tests.MSTest/README.md @@ -0,0 +1,2 @@ + +This is the `Messenger.Tests.MSTest` project, it holds the test code for the [Messenger](../Messenger/) project and mirrors it's directory structure. diff --git a/Messenger/README.md b/Messenger/README.md new file mode 100644 index 00000000..3560cd08 --- /dev/null +++ b/Messenger/README.md @@ -0,0 +1,8 @@ +This is the root directory of the Messenger source code. + +It contains the following projects: +- [Messenger](Messenger/), holds the `UWP` GUI +- [Messenger.Core](Messenger.Core/), holds the core/backend functionality and data models +- [Messenger.SignalR](Messenger.SignalR/), defines the `SignalR` *hub* used for message passing between clients +- [Messenger.Core.Tests.MSTest](Messenger.Core.Tests.MSTest/), holds the test code for the [Messenger.Core](Messenger.Core/) project +- [Messenger.Tests.MSTest](Messenger.Tests.MSTest/), holds the test code for the [Messenger](Messenger/) project From 75c7abf51407918c0d5b62a09d542236d4762d7d Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 16 Aug 2021 10:51:33 +0200 Subject: [PATCH 02/10] docs(`Messenger.Core.Models`): document all entities --- Messenger/Messenger.Core/Models/Channel.cs | 1 - Messenger/Messenger.Core/Models/Membership.cs | 23 +++++++++++++++ Messenger/Messenger.Core/Models/Mention.cs | 19 ++++++++++++ .../Messenger.Core/Models/MentionTarget.cs | 2 +- .../Messenger.Core/Models/Mentionable.cs | 15 +++++++++- Messenger/Messenger.Core/Models/Message.cs | 28 ++++++++++++++++-- .../Messenger.Core/Models/Notification.cs | 22 ++++++++++++++ .../Messenger.Core/Models/NotificationMute.cs | 29 +++++++++++++++++++ .../Models/NotificationSource.cs | 3 ++ .../Messenger.Core/Models/NotificationType.cs | 3 ++ .../Messenger.Core/Models/Permissions.cs | 3 ++ Messenger/Messenger.Core/Models/Reaction.cs | 18 ++++++++++++ .../Messenger.Core/Models/SignalREventArgs.cs | 18 ++++++++++++ Messenger/Messenger.Core/Models/Team.cs | 25 ++++++++++++++++ Messenger/Messenger.Core/Models/TeamRole.cs | 21 ++++++++++++-- Messenger/Messenger.Core/Models/User.cs | 27 +++++++++++++++-- Messenger/Messenger.Core/readme.txt | 2 -- 17 files changed, 246 insertions(+), 13 deletions(-) delete mode 100644 Messenger/Messenger.Core/readme.txt diff --git a/Messenger/Messenger.Core/Models/Channel.cs b/Messenger/Messenger.Core/Models/Channel.cs index 4da736af..7a9ffdd9 100644 --- a/Messenger/Messenger.Core/Models/Channel.cs +++ b/Messenger/Messenger.Core/Models/Channel.cs @@ -1,6 +1,5 @@ namespace Messenger.Core.Models { - /// /// The source code side representation of a team's channel /// diff --git a/Messenger/Messenger.Core/Models/Membership.cs b/Messenger/Messenger.Core/Models/Membership.cs index 6f59eb9a..b5e85cc2 100644 --- a/Messenger/Messenger.Core/Models/Membership.cs +++ b/Messenger/Messenger.Core/Models/Membership.cs @@ -1,15 +1,38 @@ namespace Messenger.Core.Models { + /// + /// The source code side representation of a User's Membership in a team + /// public class Membership { + /// + /// The unique id of the Membership + /// public uint MembershipId { get; set; } + /// + /// The id of the user the membership belongs to + /// public string UserId { get; set; } + /// + /// The id of the team the user is a member of + /// public uint TeamId { get; set; } + /// + /// The roles the user has in the team + /// public string UserRole { get; set; } + /// + /// Default initialize all members(string values get initialized to "" instead of null) + /// + public Membership() + { + UserId = ""; + UserRole = ""; + } public override string ToString() { return $"MembershipId={MembershipId}, UserId={UserId}, TeamId={TeamId}, UserRole={UserRole}"; diff --git a/Messenger/Messenger.Core/Models/Mention.cs b/Messenger/Messenger.Core/Models/Mention.cs index 4b3b20be..2ba5fe9f 100644 --- a/Messenger/Messenger.Core/Models/Mention.cs +++ b/Messenger/Messenger.Core/Models/Mention.cs @@ -1,14 +1,33 @@ namespace Messenger.Core.Models { + /// + /// The source code side representation of a Mention + /// public class Mention { + /// + /// The unique id of the mention + /// public uint Id { get; set; } + /// + /// The type of entity to mention + /// public MentionTarget TargetType { get; set; } + /// + /// The id of the entity to mention + /// public string TargetId { get; set; } + /// + /// The id of the user mention an entity + /// public string MentionerId { get; set; } + + /// + /// Default initialize all members(string values get initialized to "" instead of null) + /// public Mention() { TargetId = ""; diff --git a/Messenger/Messenger.Core/Models/MentionTarget.cs b/Messenger/Messenger.Core/Models/MentionTarget.cs index 9aa9f293..9e363e37 100644 --- a/Messenger/Messenger.Core/Models/MentionTarget.cs +++ b/Messenger/Messenger.Core/Models/MentionTarget.cs @@ -1,7 +1,7 @@ namespace Messenger.Core.Models { /// - /// Represents an entity that can be mentioned in a message + /// Holds mentionable entity types /// public enum MentionTarget { diff --git a/Messenger/Messenger.Core/Models/Mentionable.cs b/Messenger/Messenger.Core/Models/Mentionable.cs index 53444e8c..e403e16f 100644 --- a/Messenger/Messenger.Core/Models/Mentionable.cs +++ b/Messenger/Messenger.Core/Models/Mentionable.cs @@ -1,16 +1,29 @@ namespace Messenger.Core.Models { /// - /// Holds information about a mentionable entity + /// Holds information about a mentionable entity and is intended to + /// be used in dialogs to insert a mention in a message /// public class Mentionable { + /// + /// The type of entity to mention + /// public MentionTarget TargetType { get; set; } + /// + /// The id of the concrete entity to mention + /// public string TargetId { get; set; } + /// + /// The name of the concrete entity to mention + /// public string TargetName { get; set; } + /// + /// Default initialize all members(string values get initialized to "" instead of null) + /// public Mentionable() { TargetId = ""; diff --git a/Messenger/Messenger.Core/Models/Message.cs b/Messenger/Messenger.Core/Models/Message.cs index 48dddce4..bd35c131 100644 --- a/Messenger/Messenger.Core/Models/Message.cs +++ b/Messenger/Messenger.Core/Models/Message.cs @@ -4,32 +4,54 @@ namespace Messenger.Core.Models { /// - /// An abstract class of a message used asa base for Privatemessage and Teammessage + /// The source code side representation of a Message /// public class Message { + /// + /// The unique id of the message + /// public uint Id { get; set; } + /// + /// The id of the messages's sender + /// public string SenderId { get; set; } + /// + /// The actual content of the message + /// public string Content { get; set; } + /// + /// The time at which the message was created + /// public DateTime CreationTime { get; set; } /// - /// Channel where the message was posted + /// The id of the channel the message was sent to /// public uint RecipientId { get; set; } /// - /// Null in case of a Top-level message + /// The optional parent of the message (which this one is a reply to) /// public uint? ParentMessageId { get; set; } + /// + /// The id of the user who sent the message + /// public User Sender { get; set; } + /// + /// The list of blob names representing the message attachments + /// public List AttachmentsBlobName { get; set; } + /// + /// Default initialize all members(string values get initialized to "" instead of null + /// and Lists get initialized to an empty one instead of null) + /// public Message() { SenderId = ""; diff --git a/Messenger/Messenger.Core/Models/Notification.cs b/Messenger/Messenger.Core/Models/Notification.cs index 4e4a00eb..c3078c67 100644 --- a/Messenger/Messenger.Core/Models/Notification.cs +++ b/Messenger/Messenger.Core/Models/Notification.cs @@ -4,13 +4,35 @@ namespace Messenger.Core.Models { + /// + /// The source code side representation of a Notification + /// public class Notification { + /// + /// The unique id of the notification + /// public uint Id { get; set; } + + /// + /// The id of the user who receives the notification + /// public string RecipientId { get; set; } + + /// + /// The time at which the notification was created + /// public DateTime CreationTime { get; set; } + + + /// + /// A JSON representation of the actual notification content + /// public JObject Message { get; set; } + /// + /// Default initialize all members(string values get initialized to "" instead of null) + /// public Notification() { RecipientId = ""; diff --git a/Messenger/Messenger.Core/Models/NotificationMute.cs b/Messenger/Messenger.Core/Models/NotificationMute.cs index d985dd90..a1da81ba 100644 --- a/Messenger/Messenger.Core/Models/NotificationMute.cs +++ b/Messenger/Messenger.Core/Models/NotificationMute.cs @@ -1,14 +1,43 @@ namespace Messenger.Core.Models { + /// + /// The source code side representation of a NotificationMute used to mute notifications + /// public class NotificationMute { + /// + /// The unique id of the NotificationMute + /// public uint Id { get; set; } + + /// + /// The type of notification to mute + /// public NotificationType? NotificationType { get; set; } + + /// + /// The type of notification source to mute + /// public NotificationSource? NotificationSourceType { get; set; } + + /// + /// The id of the concrete notification source to mute + /// public string NotificationSourceValue { get; set; } + + /// + /// The id of the user who triggered the sending through his action to mute + /// public string SenderId { get; set; } + + /// + /// The id of the user who mutes the notification + /// public string UserId { get; set; } + /// + /// Default initialize all members(string values get initialized to "" instead of null) + /// public NotificationMute() { NotificationSourceValue = ""; diff --git a/Messenger/Messenger.Core/Models/NotificationSource.cs b/Messenger/Messenger.Core/Models/NotificationSource.cs index feabf1dc..804dc136 100644 --- a/Messenger/Messenger.Core/Models/NotificationSource.cs +++ b/Messenger/Messenger.Core/Models/NotificationSource.cs @@ -1,5 +1,8 @@ namespace Messenger.Core.Models { + /// + /// Holds types of notification sources + /// public enum NotificationSource { Team, diff --git a/Messenger/Messenger.Core/Models/NotificationType.cs b/Messenger/Messenger.Core/Models/NotificationType.cs index 04b75483..2753c941 100644 --- a/Messenger/Messenger.Core/Models/NotificationType.cs +++ b/Messenger/Messenger.Core/Models/NotificationType.cs @@ -1,5 +1,8 @@ namespace Messenger.Core.Models { + /// + /// Holds types of notifications + /// public enum NotificationType { UserMentioned, diff --git a/Messenger/Messenger.Core/Models/Permissions.cs b/Messenger/Messenger.Core/Models/Permissions.cs index 6f1512bc..59ff2af5 100644 --- a/Messenger/Messenger.Core/Models/Permissions.cs +++ b/Messenger/Messenger.Core/Models/Permissions.cs @@ -1,5 +1,8 @@ namespace Messenger.Core.Models { + /// + /// Holds permissions assignable to a team's roles + /// public enum Permissions { CanAddUser, diff --git a/Messenger/Messenger.Core/Models/Reaction.cs b/Messenger/Messenger.Core/Models/Reaction.cs index ec807d05..bfd7894c 100644 --- a/Messenger/Messenger.Core/Models/Reaction.cs +++ b/Messenger/Messenger.Core/Models/Reaction.cs @@ -1,15 +1,33 @@ namespace Messenger.Core.Models { + /// + /// The source code side representation of a reaction to a message + /// public class Reaction { + /// + /// The unique id of the reaction made to a message + /// public uint Id { get; set; } + /// + /// The symbol someone reacted to a message with + /// public string Symbol { get; set; } + /// + /// The id of the user who reacted to a message + /// public string UserId{ get; set; } + /// + /// The id of the message a user reacted to + /// public uint MessageId { get; set; } + /// + /// Default initialize all members(string values get initialized to "" instead of null) + /// public Reaction() { Symbol = ""; diff --git a/Messenger/Messenger.Core/Models/SignalREventArgs.cs b/Messenger/Messenger.Core/Models/SignalREventArgs.cs index 365e76b3..8b0834c1 100644 --- a/Messenger/Messenger.Core/Models/SignalREventArgs.cs +++ b/Messenger/Messenger.Core/Models/SignalREventArgs.cs @@ -2,10 +2,19 @@ namespace Messenger.Core.Models { + /// + /// Represents event arguments to use with signalR functions + /// public class SignalREventArgs : EventArgs { + /// + /// The value of an signalR event argument + /// public T Value { get; set; } + /// + /// Build a signalR event argument with one value + /// public SignalREventArgs(T value) { Value = value; @@ -14,10 +23,19 @@ public SignalREventArgs(T value) public class SignalREventArgs : EventArgs { + /// + /// The first value of an signalR event argument + /// public TOne FirstValue { get; set; } + /// + /// The second value of an signalR event argument + /// public TTwo SecondValue { get; set; } + /// + /// Build a signalR event argument with two values + /// public SignalREventArgs(TOne firstValue, TTwo secondValue) { FirstValue = firstValue; diff --git a/Messenger/Messenger.Core/Models/Team.cs b/Messenger/Messenger.Core/Models/Team.cs index 8a24ea42..ca3d4f62 100644 --- a/Messenger/Messenger.Core/Models/Team.cs +++ b/Messenger/Messenger.Core/Models/Team.cs @@ -4,19 +4,43 @@ namespace Messenger.Core.Models { + /// + /// The source code side representation of a Team + /// public class Team { + // TODO: IDK if this makes sense (here) public ObservableCollection Channels { get; set; } + + /// + /// The unique id of the team + /// public uint Id { get; set; } + /// + /// The name of the team + /// public string Name { get; set; } + /// + /// The name of the team + /// public string Description { get; set; } + /// + /// The time at which the team was created + /// public DateTime CreationDate { get; set; } + /// + /// The members of the team + /// public List Members { get; set; } + /// + /// Default initialize all members(string values get initialized to "" instead of null + /// and List values get initialized instead of being null) + /// public Team() { Name = ""; @@ -30,6 +54,7 @@ public override string ToString() return $"Team: Id={Id}, Name={Name}, Description={Description}, CreationDate={CreationDate.ToString()}, Members=[{string.Join(",", Members)}]"; } + // TODO: IDK if this makes sense (here) #region Helpers /// /// refactors the Channels list diff --git a/Messenger/Messenger.Core/Models/TeamRole.cs b/Messenger/Messenger.Core/Models/TeamRole.cs index 0ef96f91..c225251c 100644 --- a/Messenger/Messenger.Core/Models/TeamRole.cs +++ b/Messenger/Messenger.Core/Models/TeamRole.cs @@ -1,16 +1,33 @@ namespace Messenger.Core.Models { + /// + /// The source code side representation of a Role defined in a Team + /// public class TeamRole { + /// + /// The unique id of the role + /// public uint Id {get; set;} + + /// + /// The actual name of the rome + /// public string Role {get; set;} + + /// + /// The id of the team the role is defined in + /// public uint TeamId {get; set;} /// - /// Hex + /// The hex color code used when displaying the role /// public string Color { get; set; } + /// + /// Default initialize all members(string values get initialized to "" instead of null) + /// public TeamRole() { Role = ""; @@ -18,7 +35,7 @@ public TeamRole() public override string ToString() { - return $"TeamRole: {Id}, Role={Role}, TeamId={TeamId}"; + return $"TeamRole: {Id}, Role={Role}, TeamId={TeamId}, Color={Color}"; } } } diff --git a/Messenger/Messenger.Core/Models/User.cs b/Messenger/Messenger.Core/Models/User.cs index fe51ff49..b0ab0ea4 100644 --- a/Messenger/Messenger.Core/Models/User.cs +++ b/Messenger/Messenger.Core/Models/User.cs @@ -3,20 +3,39 @@ namespace Messenger.Core.Models { + /// + /// The source code side representation of a User + /// public class User { - // From Microsoft + /// + /// The unique id of a user(pulled form microsoft services) + /// public string Id { get; set; } + /// + /// The display name of the user + /// public string DisplayName { get; set; } + /// + /// The id used to deduplicate user names(e.g. UserXY#1, UserXY#2) + /// public uint NameId { get; set; } + /// + /// The path to the user's profile photo in the blob storage + /// public string Photo { get; set; } + /// + /// The email address of the user + /// public string Mail { get; set; } - // From Database + /// + /// The user's bio + /// public string Bio { get; set; } public User() @@ -28,13 +47,15 @@ public User() Bio = ""; } + /// + /// Default initialize all members(string values get initialized to "" instead of null) + /// public override string ToString() { return $"User: Id={Id}, DisplayName={DisplayName}, NameId={NameId}, Photo={Photo}, Mail={Mail}, Bio={Bio}"; } // TODO: Cleanup - public List Userlist { get; set; } } } diff --git a/Messenger/Messenger.Core/readme.txt b/Messenger/Messenger.Core/readme.txt deleted file mode 100644 index dd206767..00000000 --- a/Messenger/Messenger.Core/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -This core project is a .net standard project. -It's a great place to put all your logic that is not platform dependent (e.g. model/helper classes) so they can be reused. \ No newline at end of file From 133505e4d3e7b3dabe52dc11ac09959cca7df769 Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 16 Aug 2021 11:13:58 +0200 Subject: [PATCH 03/10] docs(`Messenger.Core.Helpers`): document all entities --- Messenger/Messenger.Core/Helpers/GlobalLogger.cs | 10 ++++++++-- Messenger/Messenger.Core/Helpers/Json.cs | 14 ++++++++++++++ .../Messenger.Core/Helpers/LoginResultType.cs | 3 +++ Messenger/Messenger.Core/Helpers/Mapper.cs | 5 +++++ .../Messenger.Core/Helpers/NotificationMessage.cs | 2 +- .../Helpers/NotificationMessageBuilder.cs | 2 +- Messenger/Messenger.Core/Helpers/Singleton.cs | 7 +++++++ Messenger/Messenger.Core/Helpers/SqlHelpers.cs | 3 +++ .../Messenger.Core/Helpers/StreamExtensions.cs | 8 ++++++++ 9 files changed, 50 insertions(+), 4 deletions(-) diff --git a/Messenger/Messenger.Core/Helpers/GlobalLogger.cs b/Messenger/Messenger.Core/Helpers/GlobalLogger.cs index b6dc6e1e..dc15d8ee 100644 --- a/Messenger/Messenger.Core/Helpers/GlobalLogger.cs +++ b/Messenger/Messenger.Core/Helpers/GlobalLogger.cs @@ -3,11 +3,17 @@ namespace Messenger.Core.Helpers { + /// + /// Configures a logger to log at /BIB_VPR/log.txt + /// public static class GlobalLogger { private static ILogger _instance; - public static ILogger Instance => _instance ?? + /// + /// The actual logger instance + /// + public static ILogger Instance => _instance ?? (_instance = new LoggerConfiguration() .Enrich.FromLogContext() .WriteTo.File(Path.Combine(Path.GetTempPath(), "BIB_VPR", "log.txt"), @@ -18,4 +24,4 @@ public static class GlobalLogger restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information) .CreateLogger()); } -} \ No newline at end of file +} diff --git a/Messenger/Messenger.Core/Helpers/Json.cs b/Messenger/Messenger.Core/Helpers/Json.cs index db31c30d..c12ccefa 100644 --- a/Messenger/Messenger.Core/Helpers/Json.cs +++ b/Messenger/Messenger.Core/Helpers/Json.cs @@ -4,8 +4,17 @@ namespace Messenger.Core.Helpers { + /// + /// Holds static methods to work with JSON + /// public static class Json { + /// + /// Deserialize a JSON encoded string to an instance of a type + /// + /// The JSON encoded string to deserialize + /// The type to convert to + /// The object resulting from the deserialization public static async Task ToObjectAsync(string value) { return await Task.Run(() => @@ -14,6 +23,11 @@ public static async Task ToObjectAsync(string value) }); } + /// + /// Serialize an object to a JSON encoded string + /// + /// The object to serialize + /// The JSON encoded string resulting from the serialization public static async Task StringifyAsync(object value) { return await Task.Run(() => diff --git a/Messenger/Messenger.Core/Helpers/LoginResultType.cs b/Messenger/Messenger.Core/Helpers/LoginResultType.cs index 2ff1056f..94f33d99 100644 --- a/Messenger/Messenger.Core/Helpers/LoginResultType.cs +++ b/Messenger/Messenger.Core/Helpers/LoginResultType.cs @@ -1,5 +1,8 @@ namespace Messenger.Core.Helpers { + /// + /// Holds status values of login attempts + /// public enum LoginResultType { Success, diff --git a/Messenger/Messenger.Core/Helpers/Mapper.cs b/Messenger/Messenger.Core/Helpers/Mapper.cs index 7782da5b..21a6587e 100644 --- a/Messenger/Messenger.Core/Helpers/Mapper.cs +++ b/Messenger/Messenger.Core/Helpers/Mapper.cs @@ -11,6 +11,9 @@ namespace Messenger.Core.Helpers { + /// + /// Holds static methods to convert (mostly) from data rows to other types or classes + /// public class Mapper { public static ILogger logger => GlobalLogger.Instance; @@ -154,6 +157,7 @@ public static Notification NotificationFromDataRow(DataRow row) }; } + /// /// Maps to a full Mention model from the data rows /// /// DataRow from the DataSet @@ -243,6 +247,7 @@ public static JObject strToJObject(object str) return JObject.Parse(str as string); } + /// /// Convert a specified column of a dataRow to an enum /// /// The type of the enum to convert to diff --git a/Messenger/Messenger.Core/Helpers/NotificationMessage.cs b/Messenger/Messenger.Core/Helpers/NotificationMessage.cs index 6ad0c311..33221f0f 100644 --- a/Messenger/Messenger.Core/Helpers/NotificationMessage.cs +++ b/Messenger/Messenger.Core/Helpers/NotificationMessage.cs @@ -4,7 +4,7 @@ namespace Messenger.Core.Helpers { /// - /// Handles serialization and deserialization of notification messages + /// Holds static methods to work with Notification Messages /// public static class NotificationMessage { diff --git a/Messenger/Messenger.Core/Helpers/NotificationMessageBuilder.cs b/Messenger/Messenger.Core/Helpers/NotificationMessageBuilder.cs index dd007b6b..890d70fb 100644 --- a/Messenger/Messenger.Core/Helpers/NotificationMessageBuilder.cs +++ b/Messenger/Messenger.Core/Helpers/NotificationMessageBuilder.cs @@ -7,7 +7,7 @@ namespace Messenger.Core.Helpers { /// - /// Contains static methods to create notification messages from minimal information + /// Holds static methods to create notification messages from minimal information /// public static class NotificationMessageBuilder { diff --git a/Messenger/Messenger.Core/Helpers/Singleton.cs b/Messenger/Messenger.Core/Helpers/Singleton.cs index ba985c74..37bfc071 100644 --- a/Messenger/Messenger.Core/Helpers/Singleton.cs +++ b/Messenger/Messenger.Core/Helpers/Singleton.cs @@ -3,11 +3,18 @@ namespace Messenger.Core.Helpers { + /// + /// Represents a singleton instance holding an object + /// + /// The type to store in the instance public static class Singleton where T : new() { private static ConcurrentDictionary _instances = new ConcurrentDictionary(); + /// + /// Access the singleton instance's type + /// public static T Instance { get diff --git a/Messenger/Messenger.Core/Helpers/SqlHelpers.cs b/Messenger/Messenger.Core/Helpers/SqlHelpers.cs index f65fec63..4df48a49 100644 --- a/Messenger/Messenger.Core/Helpers/SqlHelpers.cs +++ b/Messenger/Messenger.Core/Helpers/SqlHelpers.cs @@ -11,6 +11,9 @@ namespace Messenger.Core.Helpers { + /// + /// Holds static methods for common sql operations + /// public class SqlHelpers : AzureServiceBase { /// diff --git a/Messenger/Messenger.Core/Helpers/StreamExtensions.cs b/Messenger/Messenger.Core/Helpers/StreamExtensions.cs index 935e725c..5a7ba1bc 100644 --- a/Messenger/Messenger.Core/Helpers/StreamExtensions.cs +++ b/Messenger/Messenger.Core/Helpers/StreamExtensions.cs @@ -3,8 +3,16 @@ namespace Messenger.Core.Helpers { + /// + /// Holds static methods for efficient data streaming + /// public static class StreamExtensions { + /// + /// Convert a stream to a base64 encoded string + /// + /// The stream to encode + /// The base64 representation of stream public static string ToBase64String(this Stream stream) { using (var memoryStream = new MemoryStream()) From fe97efe2ae1adc7c45971dd66850be5e63881c1a Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 16 Aug 2021 11:19:14 +0200 Subject: [PATCH 04/10] chore: remove unneeded projects --- .../Messenger.Console.csproj | 8 - Messenger/Messenger.Console/Program.cs | 12 - .../IMessengerApp.cs | 7 - .../Messenger.ConsoleMessenger.csproj | 26 --- .../MessengerApp.cs | 209 ------------------ .../Models/ChatMenuOption.cs | 12 - .../Programs/ChatPage.cs | 155 ------------- .../Programs/HomePage.cs | 24 -- .../Programs/MessengerProgram.cs | 32 --- .../Messenger.ConsoleMessenger/Runner.cs | 50 ----- .../appsettings.json | 11 - 11 files changed, 546 deletions(-) delete mode 100644 Messenger/Messenger.Console/Messenger.Console.csproj delete mode 100644 Messenger/Messenger.Console/Program.cs delete mode 100644 Messenger/Messenger.ConsoleMessenger/IMessengerApp.cs delete mode 100644 Messenger/Messenger.ConsoleMessenger/Messenger.ConsoleMessenger.csproj delete mode 100644 Messenger/Messenger.ConsoleMessenger/MessengerApp.cs delete mode 100644 Messenger/Messenger.ConsoleMessenger/Models/ChatMenuOption.cs delete mode 100644 Messenger/Messenger.ConsoleMessenger/Programs/ChatPage.cs delete mode 100644 Messenger/Messenger.ConsoleMessenger/Programs/HomePage.cs delete mode 100644 Messenger/Messenger.ConsoleMessenger/Programs/MessengerProgram.cs delete mode 100644 Messenger/Messenger.ConsoleMessenger/Runner.cs delete mode 100644 Messenger/Messenger.ConsoleMessenger/appsettings.json diff --git a/Messenger/Messenger.Console/Messenger.Console.csproj b/Messenger/Messenger.Console/Messenger.Console.csproj deleted file mode 100644 index 20827042..00000000 --- a/Messenger/Messenger.Console/Messenger.Console.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - Exe - net5.0 - - - diff --git a/Messenger/Messenger.Console/Program.cs b/Messenger/Messenger.Console/Program.cs deleted file mode 100644 index a9d68a52..00000000 --- a/Messenger/Messenger.Console/Program.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace Messenger.Console -{ - class Program - { - static void Main(string[] args) - { - - } - } -} diff --git a/Messenger/Messenger.ConsoleMessenger/IMessengerApp.cs b/Messenger/Messenger.ConsoleMessenger/IMessengerApp.cs deleted file mode 100644 index 5a1e5fcd..00000000 --- a/Messenger/Messenger.ConsoleMessenger/IMessengerApp.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Messenger.ConsoleMessenger -{ - public interface IMessengerApp - { - void Run(); - } -} \ No newline at end of file diff --git a/Messenger/Messenger.ConsoleMessenger/Messenger.ConsoleMessenger.csproj b/Messenger/Messenger.ConsoleMessenger/Messenger.ConsoleMessenger.csproj deleted file mode 100644 index 126f7edc..00000000 --- a/Messenger/Messenger.ConsoleMessenger/Messenger.ConsoleMessenger.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - Exe - net5.0 - - - - - - - - - - - - - - - - - PreserveNewest - - - - diff --git a/Messenger/Messenger.ConsoleMessenger/MessengerApp.cs b/Messenger/Messenger.ConsoleMessenger/MessengerApp.cs deleted file mode 100644 index 5ab14741..00000000 --- a/Messenger/Messenger.ConsoleMessenger/MessengerApp.cs +++ /dev/null @@ -1,209 +0,0 @@ -using Messenger.ConsoleMessenger.Programs; -using Messenger.Core.Helpers; -using Messenger.Core.Models; -using Messenger.Core.Services; -using Serilog.Context; -using Serilog; -using System; -using System.Threading.Tasks; - -namespace Messenger.ConsoleMessenger -{ - public class MessengerApp : IMessengerApp - { - #region Constants - - private const string CLIENT_ID = @"ca176355-2137-4346-838b-53a79d8ed8b4"; - - #endregion - - #region Private - - private MessengerService MessengerService => Singleton.Instance; - - private IdentityService IdentityService => Singleton.Instance; - - private MicrosoftGraphService MicrosoftGraphService => Singleton.Instance; - - private UserService UserService => Singleton.Instance; - - private readonly ILogger _log; - - private User _user { get; set; } - - #endregion - - public MessengerApp() - { - IdentityService.InitializeConsoleForAadMultipleOrgs(CLIENT_ID); - - // Force to initialize with the given connection string - MessengerService.RegisterListenerForMessages(OnMessageReceived); - - _log = GlobalLogger.Instance; - } - - /// - /// Starts the application - /// - public void Run() - { - LogContext.PushProperty("Method", System.Reflection.MethodBase.GetCurrentMethod().Name); - LogContext.PushProperty("SourceContext", this.GetType().Name); - Console.ForegroundColor = ConsoleColor.Gray; - _log.Fatal("Application starting"); - - var isLoggedIn = Authenticate().GetAwaiter().GetResult(); - if (isLoggedIn) - { - OnLoginSuccess(); - - _log.Fatal("Running the messenger program...\n"); - MessengerProgram - .CreateProgram(_user) - .Run(); - } - } - - /// - /// Starts the authentication - /// - /// - private async Task Authenticate() - { - LogContext.PushProperty("Method", System.Reflection.MethodBase.GetCurrentMethod().Name); - LogContext.PushProperty("SourceContext", this.GetType().Name); - _log.Debug("Authentication in progress..."); - var result = await IdentityService.LoginAsync(); - - switch (result) - { - case LoginResultType.Success: - _log.Fatal("Login Success"); - return true; - case LoginResultType.CancelledByUser: - _log.Fatal("Authentication cancelled"); - break; - case LoginResultType.NoNetworkAvailable: - _log.Fatal("No network available"); - break; - default: - _log.Fatal("Login failed"); - break; - } - - return false; - } - - #region Events - - /// - /// Fires if the login was successful - /// - private void OnLoginSuccess() - { - LogContext.PushProperty("Method", System.Reflection.MethodBase.GetCurrentMethod().Name); - LogContext.PushProperty("SourceContext", this.GetType().Name); - - _log.Fatal("Authentication success! Starting the process to get the current user data..."); - var user = GetUserFromGraphApiAsync().GetAwaiter().GetResult(); - - _log.Fatal("All done! Logged in as {username} ({mail})", user.DisplayName, user.Mail); - _user = user; - } - - /// - /// Fires on "MessageReceived" in MessengerService - /// - /// Service that triggered the event - /// Message object retrieved from the event - private void OnMessageReceived(object sender, Message message) - { - LogContext.PushProperty("Method", System.Reflection.MethodBase.GetCurrentMethod().Name); - LogContext.PushProperty("SourceContext", this.GetType().Name); - _log.Fatal("Getting the sender information..."); - message.Sender = UserService.GetUser(message.SenderId).GetAwaiter().GetResult(); - - bool isFromSelf = message.SenderId == _user.Id; - - if (isFromSelf) - { - // Hub received the message and broadcasted back - _log.Fatal("Message was sent successfully! @ {0} as {1}", - message.CreationTime, - message.Sender.DisplayName); - } - else - { - // Message broadcasted from a member - _log.Fatal("Message Received! {0} says: {1} @{2}", - message.Sender.DisplayName, - message.Content, - message.CreationTime); - } - } - - #endregion - - #region Helpers - - /// - /// Gets the user information from Microsoft Graph Service and maps to the user model - /// - /// A complete user object - private async Task GetUserFromGraphApiAsync() - { - LogContext.PushProperty("Method", System.Reflection.MethodBase.GetCurrentMethod().Name); - LogContext.PushProperty("SourceContext", this.GetType().Name); - _log.Fatal("Getting access token for the microsoft graph service..."); - var accessToken = await IdentityService.GetAccessTokenForGraphAsync(); - - if (string.IsNullOrEmpty(accessToken)) - { - _log.Fatal("Failed to acquire the token."); - return null; - } - - _log.Fatal("Getting user data from the microsoft graph service..."); - var userData = await MicrosoftGraphService.GetUserInfoAsync(accessToken); - - return await GetUserModelFromData(userData); - } - - /// - /// Gets the user data from the database and merges with the data from Microsoft Graph Service - /// - /// User data from Microsoft Graph Service - /// A complete user object - private async Task GetUserModelFromData(User userData) - { - LogContext.PushProperty("Method", System.Reflection.MethodBase.GetCurrentMethod().Name); - LogContext.PushProperty("SourceContext", this.GetType().Name); - if (userData == null) - { - _log.Fatal("Failed to fetch user data from the microsoft graph service."); - return null; - } - - _log.Fatal("Getting the user from the database..."); - var userFromDatabase = await UserService.GetOrCreateApplicationUser(userData); - - // Connect to signal-r hub - // Optional parameter for connection string was given to initialize with it - _log.Fatal("Connecting to signal-r hub with the current user data..."); - await MessengerService.Initialize(userData.Id); - - _log.Information($"Current user: {userData}"); - // Merged with user model from the application database - return new User() - { - Id = userData.Id, - DisplayName = userFromDatabase.DisplayName, - Bio = userFromDatabase.Bio, - Mail = userFromDatabase.Mail - }; - } - - #endregion - } -} diff --git a/Messenger/Messenger.ConsoleMessenger/Models/ChatMenuOption.cs b/Messenger/Messenger.ConsoleMessenger/Models/ChatMenuOption.cs deleted file mode 100644 index e3ada70e..00000000 --- a/Messenger/Messenger.ConsoleMessenger/Models/ChatMenuOption.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Messenger.ConsoleMessenger.Models -{ - /// - /// Enum for the actions available in ChatPage - /// - public enum ChatMenuOption - { - Send, - View, - Exit - } -} diff --git a/Messenger/Messenger.ConsoleMessenger/Programs/ChatPage.cs b/Messenger/Messenger.ConsoleMessenger/Programs/ChatPage.cs deleted file mode 100644 index d5f58286..00000000 --- a/Messenger/Messenger.ConsoleMessenger/Programs/ChatPage.cs +++ /dev/null @@ -1,155 +0,0 @@ -using EasyConsole; -using Messenger.ConsoleMessenger.Models; -using Messenger.Core.Helpers; -using Messenger.Core.Models; -using Messenger.Core.Services; -using Serilog; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Messenger.ConsoleMessenger.Programs -{ - /// - /// MessengerProgram > HomePage > ChatPage - /// Page to join teams and send messages - /// - class ChatPage : Page - { - private MessengerService MessengerService => Singleton.Instance; - - private ILogger _logger => GlobalLogger.Instance; - - private string _userId; - - IList Teams; - - public ChatPage(Program program, string userId) - : base("Teams List", program) - { - _userId = userId; - } - - public override void Display() - { - base.Display(); - - // Shows all the teams user is in - Teams = BuildTeamsList(_userId); - foreach (var team in Teams) - { - Output.WriteLine(ConsoleColor.Green, $"Team #{team.Id, 2} {team.Name}"); - } - - // User selecting the team - uint teamId = (uint)Input.ReadInt("Select a team: ", 1, 99); - Output.WriteLine($"\nEntering team {teamId}..."); - - // User entering the team - Team selectedTeam = Teams.Where(t => t.Id == teamId).FirstOrDefault(); - Output.WriteLine($"You are now in Team '{selectedTeam.Name}'#{selectedTeam.Id}"); - - // Shows all the messages in the selected team - LoadMessages(selectedTeam); - - // Starts the action loop in the selected team - bool loopOn = true; - uint loopCount = 0; - while (loopOn) - { - if (loopCount > 0) - { - var option = Input.ReadEnum("\nWhat should we do next?"); - switch (option) - { - case ChatMenuOption.Send: - SendMessage(selectedTeam.Id); - break; - case ChatMenuOption.View: - LoadMessages(selectedTeam); - break; - case ChatMenuOption.Exit: - default: - loopOn = false; - Program.NavigateBack(); - break; - } - } - - loopCount++; - } - } - - /// - /// Loads all messages of the team - /// - /// Team to load messages from - private void LoadMessages(Team team) - { - _logger.Information("Loading messages with the current team id {0}", team.Id); - var messages = MessengerService.LoadMessages(team.Id).GetAwaiter().GetResult() ?? Enumerable.Empty(); - - _logger.Information("Total of {0} messages were loaded.", messages.Count()); - Output.WriteLine(""); - foreach (var message in messages) - { - PrintMessage(message); - } - } - - /// - /// Sends a message to the team - /// - /// Id of the team to send the message to - private void SendMessage(uint teamId) - { - var content = string.Empty; - - while (string.IsNullOrWhiteSpace(content)) - { - content = Input.ReadString($"[Enter] to send >> "); - } - - var message = new Message() - { - Content = content, - SenderId = _userId, - RecipientId = teamId, - CreationTime = DateTime.Now - }; - - MessengerService.SendMessage(message).GetAwaiter().GetResult(); - Input.ReadString(string.Empty); - } - - /// - /// Returns a list of teams the user is in - /// - /// Id of the user signed in - /// A list of teams - private IList BuildTeamsList(string userId) - { - var teams = MessengerService - .LoadTeams(userId) - .GetAwaiter() - .GetResult() - .ToList(); - - _logger.Information("Following teams are loaded: {0}", string.Join(", ", teams.Select(t => t.Name))); - - return teams; - } - - /// - /// Outputs the given message to the console - /// - /// Message to print on console - private void PrintMessage(Message message) - { - bool isFromSelf = message.SenderId == _userId; - string sender = isFromSelf ? "You" : message.Sender.DisplayName; - - Output.WriteLine($"[ {sender} ]: {message.Content} @{message.CreationTime}"); - } - } -} diff --git a/Messenger/Messenger.ConsoleMessenger/Programs/HomePage.cs b/Messenger/Messenger.ConsoleMessenger/Programs/HomePage.cs deleted file mode 100644 index 41489421..00000000 --- a/Messenger/Messenger.ConsoleMessenger/Programs/HomePage.cs +++ /dev/null @@ -1,24 +0,0 @@ -using EasyConsole; -using Messenger.Core.Models; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Messenger.ConsoleMessenger.Programs -{ - class HomePage : MenuPage - { - public HomePage(Program program) - : base("Home", program, - new Option("Join Team", () => { program.NavigateTo(); })) - { - } - - public override void Display() - { - base.Display(); - - Input.ReadString("Press [Enter] to close the application."); - } - } -} diff --git a/Messenger/Messenger.ConsoleMessenger/Programs/MessengerProgram.cs b/Messenger/Messenger.ConsoleMessenger/Programs/MessengerProgram.cs deleted file mode 100644 index a1786a3f..00000000 --- a/Messenger/Messenger.ConsoleMessenger/Programs/MessengerProgram.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Messenger.Core.Helpers; -using Messenger.Core.Models; -using Messenger.Core.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Messenger.ConsoleMessenger.Programs -{ - class MessengerProgram : EasyConsole.Program - { - public User CurrentUser { get; set; } - - public MessengerProgram(User user) - : base("Messenger Console App", breadcrumbHeader: false) - { - CurrentUser = user; - - AddPage(new HomePage(this)); - AddPage(new ChatPage(this, user.Id)); - - SetPage(); - } - - public static MessengerProgram CreateProgram(User user) - { - return new MessengerProgram(user); - } - } -} diff --git a/Messenger/Messenger.ConsoleMessenger/Runner.cs b/Messenger/Messenger.ConsoleMessenger/Runner.cs deleted file mode 100644 index 0be31d50..00000000 --- a/Messenger/Messenger.ConsoleMessenger/Runner.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Messenger.Core.Helpers; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Serilog; -using Serilog.Context; -using System; -using System.IO; - -namespace Messenger.ConsoleMessenger -{ - class Runner - { - static void Main(string[] args) - { - LogContext.PushProperty("Method", System.Reflection.MethodBase.GetCurrentMethod().Name); - LogContext.PushProperty("SourceContext", "Main"); - - var builder = new ConfigurationBuilder(); - BuildConfig(builder); - - GlobalLogger.Instance.Fatal("Setting up the application..."); - - // Register services to Host (dependency injection) - var host = Host.CreateDefaultBuilder() - .ConfigureServices((context, services) => - { - services.AddTransient(); - }) - .Build(); - - // Create the instance of MessengerApp with the dependencies - var app = ActivatorUtilities.CreateInstance(host.Services); - app.Run(); - Console.ReadKey(); - } - - /// - /// Loads the configuration settings for the application - /// - /// An instance of ConfigurationBuilder - static void BuildConfig(IConfigurationBuilder builder) - { - builder.SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) - .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true) - .AddEnvironmentVariables(); - } - } -} diff --git a/Messenger/Messenger.ConsoleMessenger/appsettings.json b/Messenger/Messenger.ConsoleMessenger/appsettings.json deleted file mode 100644 index 5fbe3ff6..00000000 --- a/Messenger/Messenger.ConsoleMessenger/appsettings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "Serilog": { - "MinimumLevel": { - "Default": "Information", - "Override": { - "Microsoft": "Information", - "System": "Warning" - } - } - } -} \ No newline at end of file From 106a26048cba6e8686135b8463df0700c2a06af8 Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 16 Aug 2021 14:26:33 +0200 Subject: [PATCH 05/10] chore: remove unnessecary files --- .../Messenger - Backup.Core.csproj | 21 ------------------- .../Properties/launchSettings.json | 7 ------- 2 files changed, 28 deletions(-) delete mode 100644 Messenger/Messenger.Core/Messenger - Backup.Core.csproj delete mode 100644 Messenger/Messenger.Core/Properties/launchSettings.json diff --git a/Messenger/Messenger.Core/Messenger - Backup.Core.csproj b/Messenger/Messenger.Core/Messenger - Backup.Core.csproj deleted file mode 100644 index 95faf6d0..00000000 --- a/Messenger/Messenger.Core/Messenger - Backup.Core.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - netstandard2.0 - Messenger.Core - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Messenger/Messenger.Core/Properties/launchSettings.json b/Messenger/Messenger.Core/Properties/launchSettings.json deleted file mode 100644 index 62d9fdaf..00000000 --- a/Messenger/Messenger.Core/Properties/launchSettings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "profiles": { - "Messenger.Core": { - "commandName": "Project" - } - } -} \ No newline at end of file From c0efda0cb7bc884c398232f460402028d3cba01f Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 16 Aug 2021 14:38:52 +0200 Subject: [PATCH 06/10] feat(`Core.Models.UploadData`): add `ToString()` method --- Messenger/Messenger.Core/Models/UploadData.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Messenger/Messenger.Core/Models/UploadData.cs b/Messenger/Messenger.Core/Models/UploadData.cs index c0dec33d..7434e2c0 100644 --- a/Messenger/Messenger.Core/Models/UploadData.cs +++ b/Messenger/Messenger.Core/Models/UploadData.cs @@ -15,5 +15,10 @@ public UploadData(Stream streamFile, string filePath) StreamFile = streamFile; FilePath = filePath; } + + public override string ToString() + { + return $"UploadData: StreamFile={StreamFile}, FilePath={FilePath}"; + } } } From 7b5d169659f806404e701a3e65d04443d51ff364 Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 16 Aug 2021 14:41:08 +0200 Subject: [PATCH 07/10] feat(`Core.Models.UploadData`): add docstrings --- Messenger/Messenger.Core/Models/UploadData.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Messenger/Messenger.Core/Models/UploadData.cs b/Messenger/Messenger.Core/Models/UploadData.cs index 7434e2c0..d8a2552d 100644 --- a/Messenger/Messenger.Core/Models/UploadData.cs +++ b/Messenger/Messenger.Core/Models/UploadData.cs @@ -5,11 +5,23 @@ namespace Messenger.Core.Models { + /// + /// Holds a Stream of data and a file path intended to safe the stream's data to + /// public class UploadData { + /// + /// Holds a stream of data intended as a files content + /// public Stream StreamFile { get; set; } + /// + /// Holds A file path intended to safe the stream's data to + /// public string FilePath { get; set; } + /// + /// Fully initialize an UploadData instance + /// public UploadData(Stream streamFile, string filePath) { StreamFile = streamFile; From 91f2c67b81f2d8e764d92c73d844eb4397ae4fb6 Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 16 Aug 2021 14:41:47 +0200 Subject: [PATCH 08/10] chore(`Services.FileSharingService`): clean up last PR --- Messenger/Messenger.Core/Services/FileSharingService.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Messenger/Messenger.Core/Services/FileSharingService.cs b/Messenger/Messenger.Core/Services/FileSharingService.cs index c7aa6b0a..3cc355fe 100644 --- a/Messenger/Messenger.Core/Services/FileSharingService.cs +++ b/Messenger/Messenger.Core/Services/FileSharingService.cs @@ -62,7 +62,7 @@ public static async Task Download(string blobFileName) // TODO:Find better exception(s) to catch catch (Exception e) { - logger.Information(e, $"Return value: false"); + logger.Information(e, $"Return value: null"); return null; } @@ -78,14 +78,14 @@ public static async Task Upload(UploadData uploadFile) { LogContext.PushProperty("Method", "Upload"); LogContext.PushProperty("SourceContext", "FileSharingService"); - logger.Information($"Function called with parameters filePath={uploadFile.FilePath}"); + logger.Information($"Function called with parameters uploadFile={uploadFile}"); // Adding GUID for deduplication string blobFileName = Path.GetFileNameWithoutExtension(uploadFile.FilePath) + Path.GetExtension(uploadFile.FilePath) + "." + Guid.NewGuid().ToString(); - logger.Information($"set blobFileName to {blobFileName} from filePath={uploadFile.FilePath}"); + logger.Information($"set blobFileName to {blobFileName} from uploadFile={uploadFile}"); try { From daefe6d25148ca0eb78deed00d91cd37962ab4cc Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 16 Aug 2021 15:49:25 +0200 Subject: [PATCH 09/10] tests(`FileSharingService`): fix tests after refactor --- .../Services/FileSharingServiceTest.cs | 28 +++++++++++++++---- .../Services/FileSharingService.cs | 2 +- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Messenger/Messenger.Core.Tests.MSTest/Services/FileSharingServiceTest.cs b/Messenger/Messenger.Core.Tests.MSTest/Services/FileSharingServiceTest.cs index f1c47400..05e1d8ba 100644 --- a/Messenger/Messenger.Core.Tests.MSTest/Services/FileSharingServiceTest.cs +++ b/Messenger/Messenger.Core.Tests.MSTest/Services/FileSharingServiceTest.cs @@ -1,7 +1,9 @@ using System.Threading.Tasks; +using System; using System.IO; +using System.Text; using Messenger.Core.Services; - +using Messenger.Core.Models; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -10,18 +12,32 @@ namespace Messenger.Tests.MSTest [TestClass] public class FileSharingServiceTest { - [TestMethod] public void UploadDownload_test() { + var testName = System.Reflection.MethodBase.GetCurrentMethod().Name; + Task.Run(async () => { - string fileName = await FileSharingService.Upload(Path.GetTempFileName()); + var unicodeEncoding = new UnicodeEncoding(); + var streamContent = unicodeEncoding.GetBytes(testName + "Content"); + var memStream = new MemoryStream(streamContent.Length); + + memStream.Write(streamContent, 0, streamContent.Length); + memStream.Seek(0, SeekOrigin.Begin); + + var blobFilename = await FileSharingService.Upload(new UploadData(memStream, $"{Path.GetTempPath()}{testName}File.txt")); + Assert.IsNotNull(blobFilename); + + var resultStream = await FileSharingService.Download(blobFilename); + Assert.IsNotNull(resultStream); - bool success = await FileSharingService.Download(fileName); + var resultContent = resultStream.ToArray(); + resultStream.Read(resultContent , 0, streamContent.Length); + Assert.AreEqual(BitConverter.ToString(streamContent), BitConverter.ToString(resultContent)); - Assert.IsNotNull(fileName); - Assert.IsTrue(success); + var didDelete = await FileSharingService.Delete(blobFilename); + Assert.IsTrue(didDelete); }).GetAwaiter().GetResult(); } diff --git a/Messenger/Messenger.Core/Services/FileSharingService.cs b/Messenger/Messenger.Core/Services/FileSharingService.cs index 3cc355fe..37ba3f81 100644 --- a/Messenger/Messenger.Core/Services/FileSharingService.cs +++ b/Messenger/Messenger.Core/Services/FileSharingService.cs @@ -55,7 +55,7 @@ public static async Task Download(string blobFileName) var result = await blobClient.DownloadToAsync(downloadStream); - logger.Information($"Return value: {result}"); + logger.Information($"Return value: {downloadStream}"); return downloadStream; } From 1c5c87e08ce896dc3b5ce00156a2e3b651b8442b Mon Sep 17 00:00:00 2001 From: jonas Date: Mon, 16 Aug 2021 17:25:29 +0200 Subject: [PATCH 10/10] docs(`Messenger.Core.Services`): document all entities --- .../Services/AzureServiceBase.cs.example | 19 +++- .../Messenger.Core/Services/ChannelService.cs | 3 + .../Services/FileSharingService.cs | 14 ++- .../Messenger.Core/Services/MentionService.cs | 3 + .../Messenger.Core/Services/MessageService.cs | 3 + .../Services/MessengerService.cs | 27 ++++- .../Services/MicrosoftGraphService.cs | 14 +++ .../Services/NotificationService.cs | 3 + .../Services/PrivateChatService.cs | 5 + .../Messenger.Core/Services/SignalRService.cs | 99 ++++++++++++++++++- .../Messenger.Core/Services/TeamService.cs | 4 + .../Messenger.Core/Services/UserService.cs | 3 + 12 files changed, 186 insertions(+), 11 deletions(-) diff --git a/Messenger/Messenger.Core/Services/AzureServiceBase.cs.example b/Messenger/Messenger.Core/Services/AzureServiceBase.cs.example index 5670e317..1fd378ae 100644 --- a/Messenger/Messenger.Core/Services/AzureServiceBase.cs.example +++ b/Messenger/Messenger.Core/Services/AzureServiceBase.cs.example @@ -6,17 +6,30 @@ using Messenger.Core.Helpers; namespace Messenger.Core.Services { + /// + /// An abstract base class offering the ability to connect to an SQL DB + /// public abstract class AzureServiceBase { #region Private - private static string connectionStringTest = @"InsertConnectionStringHere"; private static string connectionStringProd = @"InsertConnectionStringHere"; - public static ILogger logger => GlobalLogger.Instance; #endregion + public static ILogger logger => GlobalLogger.Instance; + + /// + /// Return a connection object to either a production DB or a test DB. + /// + /// Set the env var BIB_VPR_DEBUG to use a test connection instead of a production connection. + /// The test connection is read from the env var BIB_VPR_CON_STRING_TEST + /// and if it does not exist, it is read from the connectionStringTest variable above. + /// The production connection is read from the env var BIB_VPR_CON_STRING_PROD + /// and if it does not exist, it is read from the connectionStringProd variable above. + /// + /// A connection object public static SqlConnection GetDefaultConnection() { string connectionString; @@ -38,4 +51,4 @@ namespace Messenger.Core.Services } } -} \ No newline at end of file +} diff --git a/Messenger/Messenger.Core/Services/ChannelService.cs b/Messenger/Messenger.Core/Services/ChannelService.cs index 76adcf13..a9a5f568 100644 --- a/Messenger/Messenger.Core/Services/ChannelService.cs +++ b/Messenger/Messenger.Core/Services/ChannelService.cs @@ -10,6 +10,9 @@ namespace Messenger.Core.Services { + /// + /// A class holding static methods to interact with channels on the DB + /// public class ChannelService: AzureServiceBase { /// diff --git a/Messenger/Messenger.Core/Services/FileSharingService.cs b/Messenger/Messenger.Core/Services/FileSharingService.cs index 37ba3f81..240f7371 100644 --- a/Messenger/Messenger.Core/Services/FileSharingService.cs +++ b/Messenger/Messenger.Core/Services/FileSharingService.cs @@ -9,12 +9,24 @@ namespace Messenger.Core.Services { + /// + /// A class holding static methods to interact with blob storage for saving and + /// retrieving message attachments + /// public class FileSharingService { - const string blobServiceConnectionString = "DefaultEndpointsProtocol=https;AccountName=vpr;AccountKey=Y/A3PMNyH7ASxIB5KobgLqeJrBGW/vNKou0Ff8MWxs3B1PbNTZ0j+Ew9PAhiMkGObziTErqZ0j693pOc+hkVHQ==;EndpointSuffix=core.windows.net"; + // TODO: This should not actually be hardcoded... + private const string blobServiceConnectionString = "DefaultEndpointsProtocol=https;AccountName=vpr;AccountKey=Y/A3PMNyH7ASxIB5KobgLqeJrBGW/vNKou0Ff8MWxs3B1PbNTZ0j+Ew9PAhiMkGObziTErqZ0j693pOc+hkVHQ==;EndpointSuffix=core.windows.net"; + /// + /// The name of the container all files are saved to + /// private const string containerName = "attachments"; + + /// + /// The path at which to cache downloaded files + /// public static readonly string localFileCachePath = Path.Combine(Path.GetTempPath(), "BIB_VPR" + Path.DirectorySeparatorChar); public static ILogger logger => GlobalLogger.Instance; diff --git a/Messenger/Messenger.Core/Services/MentionService.cs b/Messenger/Messenger.Core/Services/MentionService.cs index 380734fc..a421a9ec 100644 --- a/Messenger/Messenger.Core/Services/MentionService.cs +++ b/Messenger/Messenger.Core/Services/MentionService.cs @@ -9,6 +9,9 @@ namespace Messenger.Core.Services { + /// + /// Holds helpers and static methods to interact with mentions on the DB + /// public class MentionService : AzureServiceBase { /// diff --git a/Messenger/Messenger.Core/Services/MessageService.cs b/Messenger/Messenger.Core/Services/MessageService.cs index 9e5ca373..b98f9c6d 100644 --- a/Messenger/Messenger.Core/Services/MessageService.cs +++ b/Messenger/Messenger.Core/Services/MessageService.cs @@ -9,6 +9,9 @@ namespace Messenger.Core.Services { + /// + /// Holds static methods to interact with messages, reactions and message attachments on the DB + /// public class MessageService : AzureServiceBase { /// diff --git a/Messenger/Messenger.Core/Services/MessengerService.cs b/Messenger/Messenger.Core/Services/MessengerService.cs index 049096bd..26d230b6 100644 --- a/Messenger/Messenger.Core/Services/MessengerService.cs +++ b/Messenger/Messenger.Core/Services/MessengerService.cs @@ -11,10 +11,14 @@ namespace Messenger.Core.Services { /// - /// Container service class for message service, team service and signal-r service + /// Holds static wrappers around other Service's methods and + /// adds Message passing to notify other clients of changes /// public class MessengerService { + /// + /// The signalRService holding the connection and defined messages to send to the hub + /// public static SignalRService SignalRService => Singleton.Instance; public static ILogger logger => GlobalLogger.Instance; @@ -572,8 +576,8 @@ public static async Task RenameChannel(string channelName, uint channelId) /// /// /// Returns a list with all channels - public static async Task> GetChannelsForTeam(uint teamId) - { + public static async Task> GetChannelsForTeam(uint teamId) + { LogContext.PushProperty("Method", "GetChannelsForTeam"); LogContext.PushProperty("SourceContext", "MessengerService"); logger.Information($"Function called with parameters teamId={teamId}"); @@ -665,9 +669,9 @@ public static async Task SendInvitation(string userId, uint teamId) // Add user to the hub group if the user is connected (will be handled in SignalR) await SignalRService.SendInvitation(user, team); - + logger.Information($"Return value: true"); - + return true; } @@ -814,6 +818,13 @@ public static async Task CreateTeamRole(string role, uint teamId, string c return true; } + /// + /// Update team's role with the specified teamId and notify other clients + /// + /// The name of the role to update + /// The id of the team the role belongs to + /// Hex code of the color used to display the role + /// True if successful, false otherwise public static async Task UpdateTeamRole(uint roleId, string role, string colorCode) { LogContext.PushProperty("Method", "AddRoleToTeam"); @@ -1012,6 +1023,12 @@ public static async Task RevokePermission(uint teamId, string role, Permis #region Private Chat + /// + /// Start a private chat between two users and notify them + /// + /// The first(ego) participant of the chat + /// The second(other) participant of the chat + /// The id of the created chat's team on success, null otherwise public static async Task StartChat(string userId, string targetUserId) { LogContext.PushProperty("Method", "StartChat"); diff --git a/Messenger/Messenger.Core/Services/MicrosoftGraphService.cs b/Messenger/Messenger.Core/Services/MicrosoftGraphService.cs index 5ca02070..f5b3e595 100644 --- a/Messenger/Messenger.Core/Services/MicrosoftGraphService.cs +++ b/Messenger/Messenger.Core/Services/MicrosoftGraphService.cs @@ -8,6 +8,10 @@ namespace Messenger.Core.Services { + /// + /// Holds static methods to interact with the microsoft graph service used to + /// authenticate users and retrieve initial user data + /// public class MicrosoftGraphService { //// For more information about Get-User Service, refer to the following documentation @@ -19,6 +23,11 @@ public class MicrosoftGraphService private static string _apiServiceMe = "me/"; private static string _apiServiceMePhoto = "me/photo/$value"; + /// + /// Get a user object from a specified accessToken + /// + /// An accessToken used to authenticate a user + /// A user object holding the authenticated user's data public static async Task GetUserInfoAsync(string accessToken) { User user = null; @@ -35,6 +44,11 @@ public static async Task GetUserInfoAsync(string accessToken) return user; } + /// + /// Get a user's profile photo from a specified accessToken + /// + /// An accessToken used to authenticate a user + /// A user's profile photo as a base64 encoded string public static async Task GetUserPhoto(string accessToken) { var httpContent = await GetDataAsync($"{_graphAPIEndpoint}{_apiServiceMePhoto}", accessToken); diff --git a/Messenger/Messenger.Core/Services/NotificationService.cs b/Messenger/Messenger.Core/Services/NotificationService.cs index a8d248cc..bb7f3867 100644 --- a/Messenger/Messenger.Core/Services/NotificationService.cs +++ b/Messenger/Messenger.Core/Services/NotificationService.cs @@ -9,6 +9,9 @@ namespace Messenger.Core.Services { + /// + /// Holds helpers and static methods to interact with notifications in the DB + /// public class NotificationService : AzureServiceBase { /// diff --git a/Messenger/Messenger.Core/Services/PrivateChatService.cs b/Messenger/Messenger.Core/Services/PrivateChatService.cs index 11609f77..efec8b1c 100644 --- a/Messenger/Messenger.Core/Services/PrivateChatService.cs +++ b/Messenger/Messenger.Core/Services/PrivateChatService.cs @@ -10,6 +10,11 @@ namespace Messenger.Core.Services { + /// + /// Holds helpers and static methods to interact with private chats on the DB + /// + /// + /// public class PrivateChatService : TeamService { /// diff --git a/Messenger/Messenger.Core/Services/SignalRService.cs b/Messenger/Messenger.Core/Services/SignalRService.cs index a6fad0c4..54f71523 100644 --- a/Messenger/Messenger.Core/Services/SignalRService.cs +++ b/Messenger/Messenger.Core/Services/SignalRService.cs @@ -9,6 +9,9 @@ namespace Messenger.Core.Services { + /// + /// Holds definitions for messages to send to the signalR hub + /// public class SignalRService { #region Private @@ -146,6 +149,7 @@ public async Task CloseConnection() /// /// Joins a hub group with the current connection id /// + /// Id of the current user /// Team id as the group name /// Asynchronous task to be awaited public async Task JoinTeam(string userId, string teamId) @@ -167,6 +171,12 @@ public async Task JoinTeam(string userId, string teamId) } } + /// + /// Leaves a hub group with the current connection id + /// + /// Id of the current user + /// Team id as the group name + /// Asynchronous task to be awaited public async Task LeaveTeam(string userId, string teamId) { LogContext.PushProperty("Method", "LeaveTeam"); @@ -194,6 +204,7 @@ public async Task LeaveTeam(string userId, string teamId) /// Sends a message to a hub group /// /// A complete message object to be sent + /// Team id as the group name /// Asynchronous task to be awaited public async Task SendMessage(Message message, uint teamId) { @@ -213,6 +224,7 @@ public async Task SendMessage(Message message, uint teamId) /// Update a message's data and notify other clients /// /// The updated message object + /// Team id as the group name /// Asynchronous task to be awaited public async Task UpdateMessage(Message message, uint teamId) { @@ -226,6 +238,12 @@ public async Task UpdateMessage(Message message, uint teamId) logger.Information($"Updated message #{message.Id} from the channel #{message.RecipientId}"); } + /// + /// Delete a message and notify other clients + /// + /// The updated message object + /// Team id as the group name + /// Asynchronous task to be awaited public async Task DeleteMessage(Message message, uint teamId) { LogContext.PushProperty("Method", "DeleteMessage"); @@ -238,6 +256,12 @@ public async Task DeleteMessage(Message message, uint teamId) logger.Information($"Deleted message #{message.Id} from the channel #{message.RecipientId}"); } + /// + /// Update a message's reactions and notify other clients + /// + /// The updated message object + /// Team id as the group name + /// Asynchronous task to be awaited public async Task UpdateMessageReactions(Message message, uint teamId) { LogContext.PushProperty("Method", "UpdateMessageReactions"); @@ -262,8 +286,7 @@ public async Task UpdateMessageReactions(Message message, uint teamId) /// /// Adds the user to the hub group /// - /// Id of the user to add - /// Id the of team to add user to + /// A team object to create a team from /// Asynchronous task to be awaited public async Task CreateTeam(Team team) { @@ -277,6 +300,11 @@ public async Task CreateTeam(Team team) logger.Information($"Created team #{team.Id} ({team.CreationDate})"); } + /// + /// Update a team's data and notify other clients + /// + /// A team object to update a team from + /// Asynchronous task to be awaited public async Task UpdateTeam(Team team) { LogContext.PushProperty("Method", "UpdateTeam"); @@ -289,6 +317,11 @@ public async Task UpdateTeam(Team team) logger.Information($"Updated team '{team.Name}' #{team.Id} ({team.CreationDate})"); } + /// + /// Delete a team and notify other clients + /// + /// A team object to delete a team from + /// Asynchronous task to be awaited public async Task DeleteTeam(Team team) { LogContext.PushProperty("Method", "DeleteTeam"); @@ -305,6 +338,11 @@ public async Task DeleteTeam(Team team) #region Channel + /// + /// Create a channel and and notify other clients other clients + /// + /// Channel object to create channel from + /// Asynchronous task to be awaited public async Task CreateChannel(Channel channel) { LogContext.PushProperty("Method", "CreateChannel"); @@ -317,6 +355,11 @@ public async Task CreateChannel(Channel channel) logger.Information($"Created channel #{channel.ChannelId} in team #{channel.TeamId})"); } + /// + /// Update a channel and and notify other clients other clients + /// + /// Channel object to update channel from + /// Asynchronous task to be awaited public async Task UpdateChannel(Channel channel) { LogContext.PushProperty("Method", "UpdateChannel"); @@ -329,6 +372,11 @@ public async Task UpdateChannel(Channel channel) logger.Information($"Updated channel #{channel.ChannelId} in team #{channel.TeamId})"); } + /// + /// Delete a channel and and notify other clients other clients + /// + /// Channel object to delete channel from + /// Asynchronous task to be awaited public async Task DeleteChannel(Channel channel) { LogContext.PushProperty("Method", "DeleteChannel"); @@ -345,6 +393,11 @@ public async Task DeleteChannel(Channel channel) #region Team Roles + /// + /// Add or update a team role and notify other clients + /// + /// TeamRole object to create/update role from + /// Asynchronous task to be awaited public async Task AddOrUpdateTeamRole(TeamRole role) { LogContext.PushProperty("Method", "AddOrUpdateTeamRole"); @@ -357,6 +410,11 @@ public async Task AddOrUpdateTeamRole(TeamRole role) logger.Information($"Added/Updated team role '{role.Role}' in team #{role.TeamId})"); } + /// + /// Delete a team role and notify other clients + /// + /// TeamRole object to delete role from + /// Asynchronous task to be awaited public async Task DeleteTeamRole(TeamRole role) { LogContext.PushProperty("Method", "DeleteTeamRole"); @@ -373,6 +431,12 @@ public async Task DeleteTeamRole(TeamRole role) #region Member + /// + /// Send a user an invitation to a team and notify other clients + /// + /// Object of user to invite + /// Objecte of team to invite user to + /// Asynchronous task to be awaited public async Task SendInvitation(User user, Team team) { LogContext.PushProperty("Method", "SendInvitation"); @@ -385,6 +449,12 @@ public async Task SendInvitation(User user, Team team) logger.Information($"Sent invitation to team #{team.Id} to user #{user.Id}"); } + /// + /// Add a member to a team and notify other clients + /// + /// Object of user to add + /// Objecte of team to add user to + /// Asynchronous task to be awaited public async Task AddMember(User user, Team team) { LogContext.PushProperty("Method", "AddMember"); @@ -409,6 +479,12 @@ public async Task UpdateMember(User user, Team team) logger.Information($"Updated member #{user.Id} in team #{team.Id}"); } + /// + /// Remove a member from a team and notify other clients + /// + /// Object of user to remove + /// Objecte of team to remove user from + /// Asynchronous task to be awaited public async Task RemoveMember(User user, Team team) { LogContext.PushProperty("Method", "RemoveMember"); @@ -425,6 +501,11 @@ public async Task RemoveMember(User user, Team team) #region User + /// + /// Update a user's data and notify other clients + /// + /// Updated user object + /// Asynchronous task to be awaited public async Task UpdateUser(User user) { LogContext.PushProperty("Method", "UpdateUser"); @@ -441,6 +522,10 @@ public async Task UpdateUser(User user) #region Helpers + /// + /// Reconnect to the signalR hub after a 500ms delay + /// + /// Asynchronous task to be awaited private async Task Reconnect(Exception e) { LogContext.PushProperty("Method", "Reconnect"); @@ -455,6 +540,10 @@ private async Task Reconnect(Exception e) logger.Information($"Building a new connection to the hub"); } + /// + /// Connect to the configured signalR hub + /// + /// Asynchronous task to be awaited private async Task CreateHubConnection() { LogContext.PushProperty("Method", "CreateHubConnection"); @@ -475,11 +564,17 @@ private async Task CreateHubConnection() return hubConnection; } + /// + /// Build a SignalREventArgs instance with one value + /// private SignalREventArgs BuildArgument(T value) { return new SignalREventArgs(value); } + /// + /// Build a SignalREventArgs instance with two values + /// private SignalREventArgs BuildArgument(TOne firstValue, TTwo secondValue) { return new SignalREventArgs(firstValue, secondValue); diff --git a/Messenger/Messenger.Core/Services/TeamService.cs b/Messenger/Messenger.Core/Services/TeamService.cs index 912c45e1..02c66447 100644 --- a/Messenger/Messenger.Core/Services/TeamService.cs +++ b/Messenger/Messenger.Core/Services/TeamService.cs @@ -9,6 +9,10 @@ namespace Messenger.Core.Services { + /// + /// Holds helpers and static methods to interact with teams on the DB, + /// including permissions, roles and members. + /// public class TeamService : AzureServiceBase { #region Teams Management diff --git a/Messenger/Messenger.Core/Services/UserService.cs b/Messenger/Messenger.Core/Services/UserService.cs index bbb79d17..af0d5570 100644 --- a/Messenger/Messenger.Core/Services/UserService.cs +++ b/Messenger/Messenger.Core/Services/UserService.cs @@ -10,6 +10,9 @@ namespace Messenger.Core.Services { + /// + /// Holds helpers and static methods to interact with users on the DB + /// public class UserService : AzureServiceBase { // TODO: Maybe use an enum of values like User.Name?