public void ReturnUpdatedPartyIfExecutedSuccessfully()
        {
            // Setup the client such that it will successfully update the invite.
            var entriesUpdated = new List <Entry>();

            _mockMemoryStoreClient.Setup(client => client.GetAsync <InviteDataModel>(_updatedInvite.Id))
            .ReturnsAsync(_storedInvite);
            _mockTransaction.Setup(tr => tr.UpdateAll(It.IsAny <IEnumerable <Entry> >()))
            .Callback <IEnumerable <Entry> >(entries => entriesUpdated.AddRange(entries));
            _mockTransaction.Setup(tr => tr.Dispose());

            // Set the invite updates.
            var metadataUpdates = new Dictionary <string, string> {
                { "name", "online services" }, { "timestamp", "" }
            };

            _updatedInvite.Metadata.Add(metadataUpdates);
            _updatedInvite.CurrentStatus = InviteStatusProto.Declined;

            // Perform the update operation and extract the updated invite received as a response.
            var context = Util.CreateFakeCallContext(SenderPlayerId, "");
            var request = new UpdateInviteRequest {
                UpdatedInvite = _updatedInvite
            };
            var receivedInvite = _inviteService.UpdateInvite(request, context).Result.Invite;

            // Verify that the updated invite has the expected fields set.
            Assert.NotNull(receivedInvite);
            Assert.AreEqual(_storedInvite.Id, receivedInvite.Id);
            Assert.AreEqual(_storedInvite.SenderId, receivedInvite.SenderPlayerId);
            Assert.AreEqual(_storedInvite.ReceiverId, receivedInvite.ReceiverPlayerId);
            Assert.AreEqual(_storedInvite.PartyId, receivedInvite.PartyId);
            Assert.AreEqual(InviteStatusProto.Declined, receivedInvite.CurrentStatus);
            CollectionAssert.AreEquivalent(new Dictionary <string, string> {
                { "name", "online services" }
            },
                                           receivedInvite.Metadata);

            // Verify that the same updated invite was sent to the memory store.
            Assert.AreEqual(1, entriesUpdated.Count);
            Assert.IsInstanceOf <InviteDataModel>(entriesUpdated[0]);
            var updatedStoredInvite = (InviteDataModel)entriesUpdated[0];

            Assert.AreEqual(_storedInvite.Id, updatedStoredInvite.Id);
            Assert.AreEqual(_storedInvite.SenderId, updatedStoredInvite.SenderId);
            Assert.AreEqual(_storedInvite.ReceiverId, updatedStoredInvite.ReceiverId);
            Assert.AreEqual(_storedInvite.PartyId, updatedStoredInvite.PartyId);
            Assert.AreEqual(InviteStatusDataModel.Declined, updatedStoredInvite.CurrentStatus);
            CollectionAssert.AreEquivalent(new Dictionary <string, string> {
                { "name", "online services" }
            },
                                           updatedStoredInvite.Metadata);
        }
        public void ReturnEntryNotFoundWhenThereIsNoSuchInviteWithTheGivenId()
        {
            // Setup the client such that it will claim there is no such stored invite with the given id.
            _mockMemoryStoreClient.Setup(client => client.GetAsync <InviteDataModel>(_updatedInvite.Id))
            .ReturnsAsync((InviteDataModel)null);

            var context = Util.CreateFakeCallContext(SenderPlayerId, "");
            var request = new UpdateInviteRequest {
                UpdatedInvite = _updatedInvite
            };
            var exception = Assert.ThrowsAsync <EntryNotFoundException>(() => _inviteService.UpdateInvite(request, context));

            Assert.AreEqual("No such invite with the given id found", exception.Message);
        }
        public void ReturnPermissionsDeniedWhenThePlayerIsNotInvolvedInTheInvite()
        {
            _mockMemoryStoreClient.Setup(client => client.GetAsync <InviteDataModel>(_updatedInvite.Id))
            .ReturnsAsync(_storedInvite);

            // Check that player involvement is enforced by UpdateInvite.
            var context = Util.CreateFakeCallContext("SomeoneElse", "");
            var request = new UpdateInviteRequest {
                UpdatedInvite = _updatedInvite
            };
            var exception = Assert.ThrowsAsync <RpcException>(() => _inviteService.UpdateInvite(request, context));

            Assert.That(exception.Message, Contains.Substring("not involved"));
            Assert.AreEqual(StatusCode.PermissionDenied, exception.StatusCode);
        }
        // Updates the metadata and current status. Sender, receiver and party id are ignored.
        // TODO: consider moving to FieldMasks.
        public override async Task <UpdateInviteResponse> UpdateInvite(UpdateInviteRequest request,
                                                                       ServerCallContext context)
        {
            var playerId = AuthHeaders.ExtractPlayerId(context);

            var updatedInvite = request.UpdatedInvite ??
                                throw new RpcException(new Status(StatusCode.InvalidArgument,
                                                                  "Expected non-empty updated invite"));

            if (string.IsNullOrEmpty(updatedInvite.Id))
            {
                throw new RpcException(new Status(StatusCode.InvalidArgument,
                                                  "Expected updated invite with non-empty id"));
            }

            using (var memClient = _memoryStoreClientManager.GetClient())
            {
                var invite = await memClient.GetAsync <InviteDataModel>(updatedInvite.Id) ??
                             throw new EntryNotFoundException(updatedInvite.Id,
                                                              "No such invite with the given id found");

                if (!invite.PlayerInvolved(playerId))
                {
                    throw new RpcException(new Status(StatusCode.PermissionDenied,
                                                      "The player is not involved in this invite"));
                }

                invite.CurrentStatus = ConvertToDataModel(updatedInvite.CurrentStatus);
                invite.UpdateMetadata(updatedInvite.Metadata);

                using (var transaction = memClient.CreateTransaction())
                {
                    transaction.UpdateAll(new List <Entry> {
                        invite
                    });
                }

                return(new UpdateInviteResponse {
                    Invite = ConvertToProto(invite)
                });
            }
        }