Пример #1
0
        /// <summary>
        /// Сообщить пользователю о новом запросе в друзья.
        /// </summary>
        /// <param name="userId">Идентификатор пользователя, которому поступил запрос в друзья.</param>
        /// <param name="request">Поступивший запрос в друзья.</param>
        public void NotifyUserAboutFriendRequest(Guid userId, FriendRequest request)
        {
            ComplexAccountState targetUserState = AccountStateService.Instance.GetStatusOf(userId);

            if (targetUserState == null)
            {
                throw new InvalidOperationException($"Got null target user state");
            }

            if (targetUserState.OnlineStatus == AccountOnlineStatus.Online)
            {
                using (IHttpActor actor = new HttpActor())
                {
                    string requesterAddress = $"{ targetUserState.Address }{ Subroutes.NotifyClient.NotifyFriendRequest }";
                    actor.SetRequestAddress(requesterAddress);
                    actor.AddHeader(FreengyHeaders.Server.ServerSessionTokenHeaderName, targetUserState.ClientAuth.ServerToken);

                    var result = actor.PostAsync <FriendRequest, FriendRequest>(request).Result;

                    string resultMessage = result.Success ? "Success" : result.Error.Message;

                    (
                        $"Sent friendrequest notification from '{ request.RequesterAccount.Name }' to " +
                        $"{ request.TargetAccount.Name }:{ Environment.NewLine }    { resultMessage }"
                    )
                    .WriteToConsole(ConsoleColor.DarkBlue);
                }
            }
        }
Пример #2
0
        private dynamic OnLoginRequest(dynamic arg)
        {
            //logInRequest = new SerializeHelper().DeserializeObject<LoginModel>(Request.Body);
            bool   isLoggingIn = logInRequest.IsLoggingIn;
            string direction   = isLoggingIn ? "in" : "out";

            $"Got '{ logInRequest.Account.Name }' log { direction } request".WriteToConsole();

            string userAddress = GetUserAddress(Request);

            if (string.IsNullOrEmpty(userAddress))
            {
                $"Client { logInRequest.Account.Name } didnt attach his address".WriteToConsole();
                throw new InvalidOperationException("Client address must be set in headers");
            }

            ComplexAccountState accountState = LogInOrOut(logInRequest, userAddress);

            $"'{ logInRequest.Account.Name } [{ userAddress }]' log { direction } result: { accountState.OnlineStatus }".WriteToConsole();

            // сложный аккаунт нужно упростить, иначе при дефолтной сериализации получается бесконечная рекурсия ссылающихся друг на друга свойств

            var jsonResponse = new JsonResponse <AccountStateModel>(accountState.ToSimple(), new DefaultJsonSerializer());

            SetAuthHeaders(jsonResponse.Headers, accountState.ClientAuth);

            SetNextPasswordData(logInRequest);

            $"Logged '{ logInRequest.Account.Name }' { direction }".WriteToConsole(isLoggingIn ? ConsoleColor.Green : ConsoleColor.Magenta);

            return(jsonResponse);
        }
Пример #3
0
        /// <summary>
        /// Notify user about appeared reaction for his friendrequest.
        /// </summary>
        /// <param name="requesterId"></param>
        /// <param name="requestReply"></param>
        public void NotifyUserAboutFriendReply(Guid requesterId, FriendRequestReply requestReply)
        {
            ComplexAccountState requesterState = AccountStateService.Instance.GetStatusOf(requesterId);

            if (requesterState == null)
            {
                throw new InvalidOperationException($"Got null requester state");
            }

            if (requesterState.OnlineStatus == AccountOnlineStatus.Online)
            {
                using (IHttpActor actor = new HttpActor())
                {
                    string requesterAddress = $"{requesterState.Address}{Subroutes.NotifyClient.NotifyFriendRequestState}";
                    actor.SetRequestAddress(requesterAddress);
                    actor.AddHeader(FreengyHeaders.Server.ServerSessionTokenHeaderName, requesterState.ClientAuth.ServerToken);

                    var result = actor.PostAsync <FriendRequestReply, FriendRequestReply>(requestReply).Result;

                    string resultMessage = result.Success ? "Success" : result.Error.Message;

                    $"Sent friendrequest reply '{ requestReply.Reaction }' to { requesterState.ComplexAccount.Name }:{ Environment.NewLine }    { resultMessage }"
                    .WriteToConsole(ConsoleColor.Blue);
                }
            }
        }
        /// <summary>
        /// Check if user is authorized.
        /// </summary>
        /// <param name="requesterId">Target use identifier.</param>
        /// <param name="requesterToken">Target user session token.</param>
        /// <returns>True if user is authorized.</returns>
        public bool IsAuthorized(Guid requesterId, string requesterToken)
        {
            ComplexAccountState requesterAccountState = GetStatusOf(requesterId);

            bool isAuthorized =
                requesterAccountState != null &&
                requesterAccountState.OnlineStatus != AccountOnlineStatus.Offline &&
                requesterAccountState.ClientAuth.ClientToken == requesterToken;

            return(isAuthorized);
        }
Пример #5
0
        /// <summary>
        /// Преобразовать сложную серверную модель в простую для отправки юзеру.
        /// </summary>
        /// <param name="complexModel"></param>
        /// <returns></returns>
        public static AccountStateModel ToSimple(this ComplexAccountState complexModel)
        {
            var simpleModel = new AccountStateModel
            {
                Address      = complexModel.Address,
                OnlineStatus = complexModel.OnlineStatus,
                AccountModel = complexModel.ComplexAccount.ToSimpleModel()
            };

            return(simpleModel);
        }
Пример #6
0
        private static void NotifyFriendAboutUser(ComplexAccountState userState, ComplexAccountState friendAccountState)
        {
            using (IHttpActor actor = new HttpActor())
            {
                string targetFriendAddress = $"{friendAccountState.Address}{Subroutes.NotifyClient.NotifyFriendState}";
                actor.SetRequestAddress(targetFriendAddress);
                actor.AddHeader(FreengyHeaders.Server.ServerSessionTokenHeaderName, friendAccountState.ClientAuth.ServerToken);

                var result = actor.PostAsync <AccountStateModel, AccountStateModel>(userState.ToSimple()).Result;
            }
        }
Пример #7
0
        /// <summary>
        /// Send informing message to a friend about user account state change.
        /// </summary>
        /// <param name="userState"></param>
        /// <param name="friendId"></param>
        public void NotifyFriendAboutUserChange(Guid friendId, ComplexAccountState userState)
        {
            ComplexAccountState friendAccountState = AccountStateService.Instance.GetStatusOf(friendId);

            if (friendAccountState == null)
            {
                throw new InvalidOperationException($"Got null friend state");
            }

            if (friendAccountState.OnlineStatus == AccountOnlineStatus.Online)
            {
                NotifyFriendAboutUser(userState, friendAccountState);
            }
        }
Пример #8
0
        public void NotifyUserOfExpAddition(ComplexAccountState userState, GainExpModel expModel)
        {
            using (IHttpActor actor = new HttpActor())
            {
                //TODO добавить начисление экспы
                string address = $"{userState.Address}{Subroutes.NotifyClient.SyncExp}";
                actor.SetRequestAddress(address);
                actor.AddHeader(FreengyHeaders.Server.ServerSessionTokenHeaderName, userState.ClientAuth.ServerToken);

                $"Giving { expModel.Amount } exp to { userState.ComplexAccount.Name } for { expModel.GainReason }"
                .WriteToConsole(ConsoleColor.Yellow);

                var result = actor.PostAsync <GainExpModel, GainExpModel>(expModel).Result;
            }
        }
        private void CacheNewState(UserAccountModel accountModel, string address)
        {
            accountModel.LastLogInTime = DateTime.Now;

            var newState = new AccountStateModel
            {
                Address      = address,
                AccountModel = accountModel,
                OnlineStatus = AccountOnlineStatus.Offline
            };

            var complexState = new ComplexAccountState(newState);

            complexState.ClientAuth.ClientToken = CreateNewToken();
            complexState.ClientAuth.ServerToken = CreateNewToken();
            accountStates.Add(complexState);
        }
Пример #10
0
        private static ComplexAccountState LogInOrOut(LoginModel logInRequest, string userAddress)
        {
            bool isLoggingIn  = logInRequest.IsLoggingIn;
            var  stateService = AccountStateService.Instance;
            var  targetStatus = isLoggingIn ? AccountOnlineStatus.Online : AccountOnlineStatus.Offline;

            ComplexAccountState complexAccountState =
                isLoggingIn ?
                stateService.LogIn(logInRequest.Account.Name, userAddress) :
                stateService.LogOut(logInRequest.Account.Name);

            if (complexAccountState.OnlineStatus == targetStatus)
            {
                Task.Run(() => UserInformerService.Instance.NotifyAllFriendsAboutUser(complexAccountState));
            }

            return(complexAccountState);
        }
        /// <summary>
        /// Log the user in.
        /// </summary>
        /// <param name="userName">User account name.</param>
        /// <param name="userAddress">User address.</param>
        /// <returns>Account state model and user authentication.</returns>
        public ComplexAccountState LogIn(string userName, string userAddress)
        {
            ComplexAccountState accountState = GetStatusOf(userName);

            if (accountState == null)
            {
                throw new UserNotFoundException(userName);
            }

            accountState.Address = userAddress;
            accountState.ClientAuth.ClientToken       = CreateNewToken();
            accountState.ClientAuth.ServerToken       = CreateNewToken();
            accountState.ComplexAccount.LastLogInTime = DateTime.Now;
            accountState.OnlineStatus = AccountOnlineStatus.Online;

            AccountDbInteracter.Instance.AddOrUpdate(accountState.ComplexAccount);

            return(accountState);
        }
Пример #12
0
        private dynamic OnSyncAccountRequest(dynamic arg)
        {
            var stateService = AccountStateService.Instance;

            Guid        senderId   = Request.Headers.GetClientId();
            SessionAuth clientAuth = Request.Headers.GetSessionAuth();

            if (!stateService.IsAuthorized(senderId, clientAuth.ClientToken))
            {
                throw new ClientNotAuthorizedException(senderId);
            }

            ComplexAccountState currentState = AccountStateService.Instance.GetStatusOf(senderId);

            var responce = new JsonResponse <AccountStateModel>(currentState.ToSimple(), new DefaultJsonSerializer());

            responce.Headers.Add(FreengyHeaders.Server.ServerSessionTokenHeaderName, currentState.ClientAuth.ServerToken);

            return(responce);
        }
Пример #13
0
        /// <summary>
        /// Отправить уведомления всем друзьям юзера о любом изменении состояния его аккаунта.
        /// </summary>
        /// <param name="userState">Модель состояния аккаунта юзера.</param>
        public void NotifyAllFriendsAboutUser(ComplexAccountState userState)
        {
            var outFriendIds =
                FriendshipService.Instance.FindByInvoker(userState.ComplexAccount.Id)
                .Select(friendship => friendship.AcceptorAccountId);

            var inFriendIds =
                FriendshipService.Instance.FindByAcceptor(userState.ComplexAccount.Id)
                .Select(friendship => friendship.ParentId);

            var allFriendIds = inFriendIds.Union(outFriendIds);
            IEnumerable <ComplexAccountState> allFriendStates = allFriendIds.Select(friendId => AccountStateService.Instance.GetStatusOf(friendId));

            Parallel.ForEach(allFriendStates, friendState =>
            {
                if (friendState.OnlineStatus == AccountOnlineStatus.Online)
                {
                    NotifyFriendAboutUser(userState, friendState);
                }
            });
        }
Пример #14
0
        private dynamic ProcessSearchFriends(SearchRequest searchRequest, SerializeHelper helper)
        {
            var registrationService = RegistrationService.Instance;
            var friendService       = FriendshipService.Instance;

            ComplexUserAccount senderAcc = registrationService.FindById(searchRequest.SenderId);

            if (senderAcc == null)
            {
                return($"Account id {searchRequest.SenderId} is not registered");
            }

            friendService.UpdateFriendships(senderAcc);

            var stateService = AccountStateService.Instance;

            AccountStateModel AccountStateSelector(FriendshipModel friendship)
            {
                Guid friendId =
                    friendship.AcceptorAccountId == searchRequest.SenderId ?
                    friendship.ParentId :
                    friendship.AcceptorAccountId;

                ComplexAccountState complexAccountState = stateService.GetStatusOf(friendId);

                if (complexAccountState == null)
                {
                    throw new InvalidOperationException($"Found null state pair for account id { friendId }");
                }

                return(complexAccountState.ToSimple());
            }

            IEnumerable <AccountStateModel> friendStateModels = senderAcc.Friendships.Select(AccountStateSelector);

            var serialized = helper.Serialize(friendStateModels);

            return(serialized);
        }
        private static void GetClientState(ComplexAccountState complexAccountState)
        {
            using (var actor = new HttpActor())
            {
                string address = $"{complexAccountState.Address}{Subroutes.NotifyClient.RequestUserState}";
                actor
                .SetRequestAddress(address)
                .AddHeader(FreengyHeaders.Server.ServerSessionTokenHeaderName, complexAccountState.ClientAuth.ServerToken);

                HttpResponseMessage responce = null;
                actor
                .GetAsync()
                .ContinueWith(task =>
                {
                    if (task.Exception != null)
                    {
                        responce = null;
                        complexAccountState.FailResponceCount++;
                        logger.Error(task.Exception.GetReallyRootException(), "Failed to get async response");
                    }
                    else
                    {
                        responce = task.Result.Value;
                    }
                })
                .Wait();

                if (responce?.StatusCode != HttpStatusCode.OK)
                {
                    complexAccountState.FailResponceCount++;
                    string message = $"Client {complexAccountState.ComplexAccount.Name} replied wrong status '{ responce?.StatusCode }'. " +
                                     $"Count: {complexAccountState.FailResponceCount}";

                    message.WriteToConsole();
                }
            }
        }