예제 #1
0
        async Task <bool> PublishIdentity()
        {
            try
            {
                var profile = await this.repo.GetProfile();

                var identityToPublish = new XIdentity
                {
                    Id = this.ownChatId,
                    PublicIdentityKey = profile.PublicKey,
                    LastSeenUTC       = DateTime.UtcNow
                };

                var response = await this.chatClient.PublishIdentityAsync(identityToPublish);

                if (response.IsSuccess)
                {
                    if (response.Result == this.ownChatId)
                    {
                        profile.IsIdentityPublished = true;
                        Debug.Assert(profile.Id == "1");
                        await this.repo.UpdateProfile(profile);

                        return(true);
                    }

                    throw new Exception($"The server did not confirm the identity was published. Server error: {response.Result}"); // SQL Server firewall...?
                }
            }
            catch (Exception e)
            {
                this.logger.LogError(e.Message);
            }
            return(false);
        }
예제 #2
0
        internal async Task VerifyContactInAddedStateAsync(Identity addedContact)
        {
            Debug.Assert(addedContact.ContactState == ContactState.Added);
            Debug.Assert(Guid.TryParse(addedContact.Id, out var isGuid));


            var response = await this.chatClient.GetIdentityAsync(addedContact.UnverifiedId);

            if (!response.IsSuccess)
            {
                throw new InvalidOperationException($"ChatClient could not download identity: {response.Error}");
            }

            XIdentity contactAdded = response.Result;

            if (contactAdded.ContactState == ContactState.Valid)
            {
                // It's on the server marked as valid, check if the public key resolves to the expected chat id
                if (contactAdded.Id != null && contactAdded.PublicIdentityKey != null && ChatId.GenerateChatId(contactAdded.PublicIdentityKey) == contactAdded.Id)
                {
                    await this.repo.UpdateAddedContactWithPublicKey(contactAdded, addedContact.Id);

                    await this.contactListManager.ChatWorker_ContactUpdateReceived(null, addedContact.Id);

                    return;
                }
            }

            throw new InvalidOperationException("VerifyContactInAddedStateAsync failed.");
        }
예제 #3
0
        private static Student MergeIdentities(IEnumerable <XIdentity> primitives)
        {
            XIdentity first = primitives.First();

            if (primitives.Count() > 1 && !(
                    primitives.All(primitive => primitive.BaseName == first.BaseName) &&
                    primitives.All(primitive => primitive.BaseNeptun == first.BaseNeptun) &&
                    primitives.All(primitive => primitive.BaseEducationProgram == first.BaseEducationProgram) &&
                    primitives.All(primitive => primitive.OriginalEducationProgram == first.OriginalEducationProgram) &&
                    primitives.All(primitive => primitive.EffectiveSemester == first.EffectiveSemester
                                   )))
            {
                Log.Write("HIBALEHETŐSÉG: A hallgató adatai között ütközés van.");
            }

            Student student = new Student();

            student.Neptun                   = first.BaseNeptun;
            student.Name                     = first.BaseName;
            student.EducationProgram         = first.BaseEducationProgram;
            student.OriginalEducationProgram = first.OriginalEducationProgram;
            student.EffectiveSemester        = first.EffectiveSemester;
            student.Emails                   = primitives
                                               .Select(primitive => primitive.Email)
                                               .Distinct()
                                               .ToArray();

            return(student);
        }
예제 #4
0
 public bool Equals(XIdentity identity)
 {
     return
         (base.Equals(identity) &&
          this.EffectiveSemester == identity.EffectiveSemester &&
          this.Email == identity.Email &&
          this.Phone == identity.Phone);
 }
        public async Task <string> AddIdentity(XIdentity identity, Action <string, byte[]> initTlsUser)
        {
            await SemaphoreSlim.WaitAsync();

            try
            {
                if (identity == null)
                {
                    throw new ArgumentNullException(nameof(XIdentity));
                }
                if (identity.Id == null)
                {
                    throw new ArgumentNullException(nameof(XIdentity.Id));
                }
                if (identity.PublicIdentityKey == null)
                {
                    throw new ArgumentNullException(nameof(XIdentity.PublicIdentityKey));
                }
                if (ChatId.GenerateChatId(identity.PublicIdentityKey) != identity.Id)
                {
                    throw new Exception("Id and public key are unrelated.");
                }
                identity.ContactState = ContactState.Valid;

                XIdentity existing = await this.identitiesRepository.Get(identity.Id);

                if (existing == null)
                {
                    await this.identitiesRepository.Add(identity);
                }
                else
                {
                    if (!ByteArrays.AreAllBytesEqual(identity.PublicIdentityKey, existing.PublicIdentityKey))
                    {
                        throw new Exception($"Different new PublicKey for {identity.Id}. Ignoring request!");
                    }
                    existing.LastSeenUTC = DateTime.UtcNow;
                    await this.identitiesRepository.Update(existing);
                }


                if (initTlsUser != null) // TLS
                {
                    initTlsUser(identity.Id, identity.PublicIdentityKey);
                }

                this.logger.LogInformation($"Identity {identity.Id} was published.", nameof(MessageNodeRepository));
                return(identity.Id);
            }
            finally
            {
                SemaphoreSlim.Release();
            }
        }
예제 #6
0
        public async Task <byte[]> ExecutePublishIdentityAsync(Command command, Action <string, byte[]> initTlsUser)
        {
            if (command.CommandId != CommandId.PublishIdentity)
            {
                throw new InvalidOperationException();
            }

            XIdentity identityBeingPublished = command.CommandData.DeserializeXIdentityCore();
            string    result = await this.messageNodeRepository.AddIdentity(identityBeingPublished, initTlsUser);

            return(new RequestCommand(CommandId.PublishIdentity_Response, result).Serialize(CommandHeader.Yes));
        }
예제 #7
0
        public async Task UpdateAddedContactWithPublicKey(XIdentity identity, string guidId)
        {
            Guid.Parse(guidId);

            if (identity == null)
            {
                throw new ArgumentNullException(nameof(identity));
            }

            if (identity.ContactState != ContactState.Valid)
            {
                throw new Exception($"Expected IdentityState.Added but was {identity.ContactState}");
            }

            if (identity.PublicIdentityKey == null)
            {
                throw new Exception("The public key must not be null");
            }

            await SemaphoreSlim.WaitAsync();

            try
            {
                var contact = await this.contacts.Get(guidId);

                if (contact != null)
                {
                    // do not ovwerwrite the name and the image of the contact from the repository!
                    contact.UnverifiedId    = null;
                    contact.FirstSeenUtc    = identity.FirstSeenUTC;
                    contact.LastSeenUtc     = identity.LastSeenUTC;
                    contact.StaticPublicKey = identity.PublicIdentityKey;
                    contact.ContactState    = identity.ContactState;
                    await this.contacts.Update(contact);
                }
            }
            finally
            {
                SemaphoreSlim.Release();
            }
        }
예제 #8
0
        public async Task <Response <string> > PublishIdentityAsync(XIdentity identity)
        {
            var response = new Response <string>();

            try
            {
                var requestCommand = new RequestCommand(CommandId.PublishIdentity, identity).Serialize(CommandHeader.Yes);
                var tlsResponse    = await this.networkClient.SendRequestAsync(requestCommand, Transport.TCP);

                AssertOneItem(tlsResponse);

                response.Result = tlsResponse[0].CommandData.DeserializeStringCore();
                response.SetSuccess();
            }
            catch (Exception e)
            {
                this.logger.LogError(e.Message);
                response.SetError(e);
            }
            return(response);
        }
예제 #9
0
        public async Task <byte[]> ExecuteAuthenticatedRequestAsync(Command command)
        {
            switch (command.CommandId)
            {
            case CommandId.AnyNews:
            {
                string recipientId = command.CommandData.DeserializeStringCore();
                var    result      = await this.messageNodeRepository.AnyNews(recipientId);

                return(new RequestCommand(CommandId.AnyNews_Response, result).Serialize(CommandHeader.Yes));                                 // only when the client receives it via UDP a header is needed.
            }

            case CommandId.CheckForResendRequest:
            {
                XResendRequest resendRequestQuery = command.CommandData.DeserializeResendRequest();
                byte           result             = await this.messageNodeRepository.CheckForResendRequest(resendRequestQuery);

                return(new RequestCommand(CommandId.CheckForResendRequest_Response, result).Serialize(CommandHeader.Yes));
            }

            case CommandId.DownloadMessages:
            {
                string recipientId = command.CommandData.DeserializeStringCore();
                var    messages    = await this.messageNodeRepository.GetMessages(recipientId);

                if (messages.Count == 0)
                {
                    throw new CommandProtocolException("No message to download, please check with CommandId.AnyNews first.");                                     // connected clients get this error information
                }
                return(new RequestCommand(CommandId.DownloadMessage_Response, messages).Serialize(CommandHeader.Yes));
            }

            case CommandId.UploadMessage:
            {
                XMessage message = command.CommandData.DeserializeMessage();                                 // Deserialize only what's needed, blob-store the rest
                string   ack     = await this.messageNodeRepository.AddMessage(message);

                return(new RequestCommand(CommandId.UploadMessage_Response, ack).Serialize(CommandHeader.Yes));
            }

            case CommandId.UploadResendRequest:
            {
                XResendRequest resendRequest    = command.CommandData.DeserializeResendRequest();
                var            resendRequestAck = await this.messageNodeRepository.AddResendRequest(resendRequest);

                return(new RequestCommand(CommandId.UploadResendRequest_Response, resendRequestAck).Serialize(CommandHeader.Yes));
            }

            case CommandId.GetIdentity:
            {
                var       addedContactId = command.CommandData.DeserializeStringCore();
                XIdentity identity       = await this.messageNodeRepository.GetIdentityAsync(addedContactId);

                return(new RequestCommand(CommandId.GetIdentity_Response, identity).Serialize(CommandHeader.Yes));
            }

            case CommandId.PublishIdentity:
            {
                XIdentity identityBeingPublished = command.CommandData.DeserializeXIdentityCore();
                string    result = await this.messageNodeRepository.AddIdentity(identityBeingPublished, null);

                return(new RequestCommand(CommandId.PublishIdentity_Response, result).Serialize(CommandHeader.Yes));
            }

            default:
                throw new CommandProtocolException($"Unknown CommandId {command.CommandId}.");
            }
        }