Пример #1
0
        /// <summary>
        /// This method will post a new message to a private group based on the provided group id
        /// and message.
        /// </summary>
        /// <param name="context">The http context of the current request</param>
        /// <param name="groupId">The id of the group</param>
        /// <param name="message">The message to be posted</param>
        /// <returns>A task that encapsulates an either monad</returns>
        public async Task <Either <Unit, Error> > PostAsync(HttpContext context, long groupId, Message message)
        {
            try
            {
                var url         = $"/api/groups/{groupId}/messages";
                var method      = HttpMethod.Post;
                var jsonMessage = JsonConvert.SerializeObject(message);
                var content     = new StringContent(jsonMessage, Encoding.UTF8, "application/json");

                return(await _apiInteropService.SendAsync(context, method, url, content));
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <Unit, Error>(SystemErrors.Exception()));
            }
        }
        /// <summary>
        /// Adds a new direct messaging entry, if it does not already exist, and also assings the callers
        /// connection id to a signalr group based on the resulting direct messaging id.
        /// </summary>
        /// <param name="firstParticipantId">The user id of the first participant</param>
        /// <param name="secondParticipantId">The user id of the second participant</param>
        /// <returns>A Task instance</returns>
        public async Task PostNewDirectMessaging(long firstParticipantId, long secondParticipantId)
        {
            // Trying to find an existing direct messaging entry based on the users provided.
            var httpContext = Context.GetHttpContext();
            var getMonad    = await _directMessagingService.GetAsync(httpContext, firstParticipantId, secondParticipantId);

            if (getMonad is Success <DirectMessaging, Error> success)
            {
                var signalGroup = DirectMessagingName(success.Value.Id);
                var payload     = new Payload <DirectMessaging>(signalGroup, success.Value);
                await Groups.AddToGroupAsync(Context.ConnectionId, signalGroup);

                await Clients.Caller.NewDirectMessaging(payload);
            }

            // Creates a new direct messaging entry between two users.
            var directMessaging = new DirectMessaging
            {
                FirstParticipantUserId  = firstParticipantId,
                SecondParticipantUserId = secondParticipantId
            };
            var monad = await _directMessagingService.PostAsync(httpContext, directMessaging);

            switch (monad)
            {
            case Success <DirectMessaging, Error> postSuccess:
                var signalGroup = DirectMessagingName(postSuccess.Value.Id);
                var payload     = new Payload <DirectMessaging>(signalGroup, postSuccess.Value);
                await Groups.AddToGroupAsync(Context.ConnectionId, signalGroup);

                await Clients.Caller.NewDirectMessaging(payload);

                break;

            case Failure <DirectMessaging, Error> failure:
                await Clients.Caller.NewDirectMessaging(failure.Value);

                break;

            default:
                await Clients.Caller.NewDirectMessaging(SystemErrors.Exception());

                break;
            }
        }
        /// <summary>
        /// This method will delete a direct messaging entry.
        /// </summary>
        /// <param name="userId">The id of the requesting user</param>
        /// <param name="directMessagingId">The id of the group</param>
        /// <returns>An either monad</returns>
        public Either <DirectMessaging, Error> Delete(long userId, long directMessagingId)
        {
            try
            {
                return(Get(userId, directMessagingId).Bind(directMessaging =>
                {
                    _burstChatContext
                    .DirectMessaging
                    .Remove(directMessaging);

                    return new Success <DirectMessaging, Error>(directMessaging);
                }));
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <DirectMessaging, Error>(SystemErrors.Exception()));
            }
        }
Пример #4
0
        /// <summary>
        /// Will check if the provided alpha invitation code exists in the database and is valid.
        /// </summary>
        /// <param name="alphaInvitationCode">The alpha invitation code instance</param>
        /// <returns>An either monad</returns>
        private Either <Unit, Error> AlphaInvitationCodeExists(Guid alphaInvitationCode)
        {
            try
            {
                var codeExists = _burstChatContext
                                 .AlphaInvitations
                                 .Any(a => a.Code == alphaInvitationCode &&
                                      a.DateExpired >= DateTime.Now);

                return(codeExists
                    ? new Success <Unit, Error>(new Unit())
                    : new Failure <Unit, Error>(AlphaInvitationErrors.AlphaInvitationCodeIsNotValid()));
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <Unit, Error>(SystemErrors.Exception()));
            }
        }
Пример #5
0
        /// <summary>
        /// Updates an invitation's state and informs the appropriate users.
        /// </summary>
        /// <param name="invitation">The invitation to be updated</param>
        /// <returns>A Task instance</returns>
        public async Task UpdateInvitation(long id, bool accepted)
        {
            var httpContext = Context.GetHttpContext();
            var data        = new UpdateInvitation
            {
                InvitationId = id,
                Accepted     = accepted
            };
            var monad = await _userService.UpdateInvitationAsync(httpContext, data);

            var signalGroup = string.Empty;
            var invite      = new Invitation();

            switch (monad)
            {
            case Success <Invitation, Error> success when success.Value.Accepted:
                invite      = success.Value;
                signalGroup = ServerSignalName(invite.ServerId);
                await Clients.Group(signalGroup).UpdatedInvitation(invite);

                await Clients.Caller.UpdatedInvitation(invite);

                break;

            case Success <Invitation, Error> success when !success.Value.Accepted:
                invite      = success.Value;
                signalGroup = ServerSignalName(invite.ServerId);
                await Clients.Caller.UpdatedInvitation(invite);

                break;

            case Failure <Invitation, Error> failure:
                await Clients.Caller.UpdatedInvitation(failure.Value);

                break;

            default:
                await Clients.Caller.UpdatedInvitation(SystemErrors.Exception());

                break;
            }
        }
        /// <summary>
        /// This method will fetch all information about direct messaging entry.
        /// </summary>
        /// <param name="userId">The id of the requesting user</param>
        /// <param name="directMessagingId">The id of the direct messages</param>
        /// <returns>An either monad</returns>
        public Either <DirectMessaging, Error> Get(long userId, long directMessagingId)
        {
            try
            {
                var directMessaging = _burstChatContext
                                      .DirectMessaging
                                      .FirstOrDefault(dm => dm.Id == directMessagingId &&
                                                      (dm.FirstParticipantUserId == userId ||
                                                       dm.SecondParticipantUserId == userId));

                return(directMessaging is not null
                    ? new Success <DirectMessaging, Error>(directMessaging)
                    : new Failure <DirectMessaging, Error>(DirectMessagingErrors.DirectMessagesNotFound()));
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <DirectMessaging, Error>(SystemErrors.Exception()));
            }
        }
Пример #7
0
        /// <summary>
        /// This method will invoke a call to the BurstChat API for the creation of a new channel.
        /// </summary>
        /// <param name="context">The http context of the current request</param>
        /// <param name="serverId">The id of the channel</param>
        /// <param name="channel">The instance of the new channel</param>
        /// <returns>A task that encapsulates an either monad</returns>
        public async Task <Either <Channel, Error> > PostAsync(HttpContext context, int serverId, Channel channel)
        {
            try
            {
                var method = HttpMethod.Post;
                var url    = "api/channels";
                var query  = HttpUtility.ParseQueryString(string.Empty);
                query["serverId"] = serverId.ToString();
                url += $"/?{query}";
                var jsonMessage = JsonSerializer.Serialize(channel);
                var content     = new StringContent(jsonMessage, Encoding.UTF8, "application/json");

                return(await _apiInteropService.SendAsync <Channel>(context, method, url, content));
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <Channel, Error>(SystemErrors.Exception()));
            }
        }
        /// <summary>
        /// Fetches all available information about a direct messaging entry based on the provided
        /// participants.
        /// </summary>
        /// <param name="context">The http context of the current request</param>
        /// <param name="firstParticipantId">The user id of the first participant</param>
        /// <param name="secondParticipantId">The user id of the seconad participant</param>
        /// <returns>An either monad</returns>
        public async Task <Either <DirectMessaging, Error> > GetAsync(HttpContext context, long firstParticipantId, long secondParticipantId)
        {
            try
            {
                var method  = HttpMethod.Get;
                var url     = "/api/direct";
                var content = new FormUrlEncodedContent(new[]
                {
                    new KeyValuePair <string?, string?>("firstParticipantId", firstParticipantId.ToString()),
                    new KeyValuePair <string?, string?>("secondParticipantId", secondParticipantId.ToString())
                });

                return(await _apiInteropService.SendAsync <DirectMessaging>(context, method, url, content));
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <DirectMessaging, Error>(SystemErrors.Exception()));
            }
        }
        /// <summary>
        /// This method will be edit a message of a direct messaging entry.
        /// </summary>
        /// <param name="userId">The id of the requesting user</param>
        /// <param name="directMessagingId">The id of the direct messaging entry</param>
        /// <param name="message">The message instance that will be used for the edit</param>
        /// <returns>An either monad<returns>
        public Either <Message, Error> UpdateMessage(long userId, long directMessagingId, Message message)
        {
            try
            {
                if (message is null)
                {
                    return(new Failure <Message, Error>(DirectMessagingErrors.DirectMessageNotFound()));
                }

                return(Get(userId, directMessagingId).Bind <Message>(_ =>
                {
                    var entries = _burstChatContext
                                  .DirectMessaging
                                  .Include(dm => dm.Messages)
                                  .ThenInclude(dm => dm.User)
                                  .Include(dm => dm.Messages)
                                  .ThenInclude(dm => dm.Links)
                                  .Where(dm => dm.Id == directMessagingId)
                                  .Select(dm => dm.Messages.FirstOrDefault(m => m.Id == message.Id))
                                  .ToList();

                    if (entries.Count != 1)
                    {
                        return new Failure <Message, Error>(DirectMessagingErrors.DirectMessageNotFound());
                    }

                    var entry = entries.First() !;
                    entry.Links = message.GetLinksFromContent();
                    entry.Content = message.RemoveLinksFromContent();
                    entry.Edited = true;
                    _burstChatContext.SaveChanges();

                    return new Success <Message, Error>(entry);
                }));
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <Message, Error>(SystemErrors.Exception()));
            }
        }
Пример #10
0
        /// <summary>
        /// Executes a request to an Asterisk server in order to create a new aor configuration
        /// for the provided endpoint.
        /// </summary>
        /// <param name="endpoint">The endpoint name</param>
        /// <returns>A task of an either monad</returns>
        private async Task <Either <Unit, Error> > PostAorAsync(string endpoint)
        {
            try
            {
                var parameters = new
                {
                    id             = endpoint,
                    maxContacts    = 5,
                    removeExisting = true,
                    supportPath    = true
                };

                await _connection.ExecuteAsync(InsertAor, parameters);

                return(new Success <Unit, Error>(Unit.New()));
            } catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <Unit, Error>(SystemErrors.Exception()));
            }
        }
Пример #11
0
        /// <summary>
        /// This method will fetch all available messages of a direct messaging entry.
        /// If a message id is provided then 300 messages sent prior will be returned.
        /// </summary>
        /// <param name="userId">The id of the requesting user</param>
        /// <param name="directMessagingId">The id of the direct messaging entry</param>
        /// <param name="searchTerm">A search term that needs to be present in all returned messages</param>
        /// <param name="lastMessageId">The message id from which all prior messages will be fetched</param>
        /// <returns>An either monad</returns>
        public Either <IEnumerable <Message>, Error> GetMessages(long userId,
                                                                 long directMessagingId,
                                                                 string?searchTerm  = null,
                                                                 long?lastMessageId = null)
        {
            try
            {
                return(Get(userId, directMessagingId).Bind(_ =>
                {
                    var messages = _burstChatContext
                                   .DirectMessaging
                                   .Include(dm => dm.Messages)
                                   .ThenInclude(m => m.User)
                                   .Include(dm => dm.Messages)
                                   .ThenInclude(m => m.Links)
                                   .Where(dm => dm.Id == directMessagingId)
                                   .Select(dm => dm.Messages
                                           .Where(m => m.Id < (lastMessageId ?? long.MaxValue) &&
                                                  (searchTerm == null || m.Content.Contains(searchTerm)))
                                           .OrderByDescending(m => m.Id)
                                           .Take(100))
                                   .ToList()
                                   .Aggregate(new List <Message>(), (current, next) =>
                    {
                        current.AddRange(next);
                        return current;
                    })
                                   .OrderBy(m => m.Id)
                                   .ToList();

                    return new Success <IEnumerable <Message>, Error>(messages);
                }));
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <IEnumerable <Message>, Error>(SystemErrors.Exception()));
            }
        }
Пример #12
0
        /// <summary>
        /// Sends an Http request to a remote Asterisk server in order to create a new
        /// auth configuration for the provided pjsip enpoint.
        /// </summary>
        /// <param name="endpoint">The endpoint name</param>
        /// <param name="password">The endpoint password</param>
        /// <returns>A task of an either monad</returns>
        private async Task <Either <Unit, Error> > PostAuthAsync(string endpoint, Guid password)
        {
            try
            {
                var parameters = new
                {
                    id       = $"auth{endpoint}",
                    authType = "userpass",
                    username = endpoint,
                    password = password.ToString()
                };

                await _connection.ExecuteAsync(InsertAuth, parameters);

                return(new Success <Unit, Error>(Unit.New()));
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <Unit, Error>(SystemErrors.Exception()));
            }
        }
Пример #13
0
        /// <summary>
        /// Returns all invitations sent to a user.
        /// </summary>
        /// <returns>A Task instance</returns>
        public async Task GetInvitations()
        {
            var httpContext = Context.GetHttpContext();
            var monad       = await _userService.GetAllInvitationsAsync(httpContext);

            switch (monad)
            {
            case Success <IEnumerable <Invitation>, Error> success:
                await Clients.Caller.Invitations(success.Value);

                break;

            case Failure <IEnumerable <Invitation>, Error> failure:
                await Clients.Caller.Invitations(failure.Value);

                break;

            default:
                await Clients.Caller.Invitations(SystemErrors.Exception());

                break;
            }
        }
Пример #14
0
        /// <summary>
        /// Sends an email to the provided recipient that contains an one time password
        /// </summary>
        /// <param name="recipient">The recipient email address</param>
        /// <param name="oneTimePassword">The one time password to be sent</param>
        /// <returns>A task of an either monad</returns>
        public async Task <Either <Unit, Error> > SendOneTimePasswordAsync(string recipient, string oneTimePassword)
        {
            try
            {
                var sender  = _smtpOptions.Sender;
                var subject = "BurstChat reset password";
                var body    = $"BurstChat account one time password: {oneTimePassword}";
                await _smtpClient.SendMailAsync(sender, recipient, subject, body);

                return(new Success <Unit, Error>(new Unit()));
            }
            catch (Exception e)
            {
                if (_webHostEnvironment.IsDevelopment())
                {
                    _logger.LogInformation($"[email: {recipient}] one time pass {oneTimePassword}");
                    return(new Success <Unit, Error>(new Unit()));
                }

                _logger.LogError(e.Message);
                return(new Failure <Unit, Error>(SystemErrors.Exception()));
            }
        }
Пример #15
0
        /// <summary>
        /// Creates a new channel for a server.
        /// </summary>
        /// <param name="serverId">The id of the server that the channel belongs</param>
        /// <param name="channel">The instance of the channel to be created</param>
        /// <returns>A task instance</returns>
        public async Task PostChannel(int serverId, Channel channel)
        {
            var httpContext = Context.GetHttpContext();
            var monad       = await _channelsService.PostAsync(httpContext, serverId, channel);

            switch (monad)
            {
            case Success <Channel, Error> success:
                var signalGroup = ServerSignalName(serverId);
                await Clients.Group(signalGroup).ChannelCreated(new dynamic[] { serverId, success.Value });

                break;

            case Failure <Channel, Error> failure:
                await Clients.Caller.ChannelCreated(failure.Value);

                break;

            default:
                await Clients.Caller.ChannelCreated(SystemErrors.Exception());

                break;
            }
        }
Пример #16
0
        /// <summary>
        /// This method will fetch all users that the requesting user has direct messaged.
        /// </summary>
        /// <param name="userId">The id of the requesting user</param>
        /// <returns>An either monad</returns>
        public Either <IEnumerable <User?>, Error> GetUsers(long userId)
        {
            try
            {
                var users = _burstChatContext
                            .DirectMessaging
                            .Include(dm => dm.FirstParticipantUser)
                            .Include(dm => dm.SecondParticipantUser)
                            .Where(dm => dm.FirstParticipantUserId == userId ||
                                   dm.SecondParticipantUserId == userId)
                            .ToList()
                            .Select(dm => dm.FirstParticipantUserId != userId
                                  ? dm.FirstParticipantUser
                                  : dm.SecondParticipantUser)
                            .ToList();

                return(new Success <IEnumerable <User?>, Error>(users));
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(new Failure <IEnumerable <User?>, Error>(SystemErrors.Exception()));
            }
        }
Пример #17
0
        /// <summary>
        /// Removes a channel from a server.
        /// </summary>
        /// <param name="serverId">The id of the server that the channel belongs</param>
        /// <param name="channelId">The id of the channel to be deleted</param>
        /// <returns>A task instance</returns>
        public async Task DeleteChannel(int serverId, int channelId)
        {
            var httpContext = Context.GetHttpContext();
            var monad       = await _channelsService.DeleteAsync(httpContext, channelId);

            switch (monad)
            {
            case Success <Channel, Error> _:
                var signalGroup = ServerSignalName(serverId);
                await Clients.Group(signalGroup).ChannelDeleted(channelId);

                break;

            case Failure <Channel, Error> failure:
                await Clients.Caller.ChannelDeleted(failure.Value);

                break;

            default:
                await Clients.Caller.ChannelDeleted(SystemErrors.Exception());

                break;
            }
        }
Пример #18
0
        /// <summary>
        /// Adds a new server and informs the caller of the results.
        /// </summary>
        /// <param name="server">The server instance to be added</param>
        /// <returns>A task instance</returns>
        public async Task AddServer(Server server)
        {
            var httpContext = Context.GetHttpContext();
            var sub         = Context;
            var monad       = await _serverService.PostAsync(httpContext, server);

            switch (monad)
            {
            case Success <Server, Error> success:
                await Clients.Caller.AddedServer(success.Value);

                break;

            case Failure <Server, Error> failure:
                await Clients.Caller.AddedServer(failure.Value);

                break;

            default:
                await Clients.Caller.AddedServer(SystemErrors.Exception());

                break;
            }
        }
Пример #19
0
        /// <summary>
        /// Informs all associated connection of a server, that its information were updated.
        /// </summary>
        /// <param name="serverId">The id of the target server</param>
        /// <returns>A task instance</returns>
        public async Task UpdateServerInfo(int serverId)
        {
            var httpContext = Context.GetHttpContext();
            var monad       = await _serverService.GetAsync(httpContext, serverId);

            switch (monad)
            {
            case Success <Server, Error> success:
                var signalGroup = ServerSignalName(serverId);
                await Clients.Group(signalGroup).UpdatedServer(success.Value);

                break;

            case Failure <Server, Error> failure:
                await Clients.Caller.UpdatedServer(failure.Value);

                break;

            default:
                await Clients.Caller.UpdatedServer(SystemErrors.Exception());

                break;
            }
        }