Example #1
0
 public async Task Connect(int userId, int projectId) // connection
 {
     if (!_connections.ContainsKey(Context.ConnectionId))
     {
         _connections.Add(Context.ConnectionId, userId);
         await ConnectToProject(projectId);
     }
 }
Example #2
0
        public void TestReplaceOnDuplicate()
        {
            IClient client1 = new FakeClient {
                AccountId = 1, SessionId = 1
            };
            IClient client2 = new FakeClient {
                AccountId = 1, SessionId = 1
            };
            var connections = new ConnectionsService();

            IClient replaced1 = connections.Add(client1);

            Assert.IsNull(replaced1);

            Assert.IsTrue(connections.TryGet(1, out IClient out1));
            Assert.IsTrue(ReferenceEquals(client1, out1));

            IClient replaced2 = connections.Add(client2);

            Assert.IsTrue(ReferenceEquals(client1, replaced2));

            Assert.IsTrue(connections.TryGet(1, out IClient out2));
            Assert.IsTrue(ReferenceEquals(client2, out2));
        }
        public override async ValueTask Handle(P08RestoreSession packet)
        {
            byte[] sessionTokenHash;
            using (var csp = SHA256.Create())
                sessionTokenHash = csp.ComputeHash(packet.SessionToken);

            // EF Core converts the C# == operator to = in SQL which compares the contents of byte arrays
            Session session = await Database.Sessions.AsTracking()
                              .SingleOrDefaultAsync(s => s.SessionId == packet.SessionId && s.SessionTokenHash == sessionTokenHash).ConfigureAwait(false);

            var response = Packets.New <P09RestoreSessionResponse>();

            if (session == null)
            {
                response.StatusCode = RestoreSessionStatus.InvalidSession;
                await Client.Send(response).ConfigureAwait(false);

                return;
            }

            session.LastConnected   = DateTime.Now;
            session.LastVersionCode = Client.VersionCode;
            await Database.SaveChangesAsync().ConfigureAwait(false);

            Client.Authenticate(session.AccountId, session.SessionId);

            response.StatusCode = RestoreSessionStatus.Success;
            await Client.Send(response).ConfigureAwait(false);

            await Delivery.StartSyncChannels(Client, packet.Channels, packet.LastMessageId).ConfigureAwait(false);

            IClient old = connections.Add(Client);

            if (old != null)
            {
                _ = old.DisposeAsync(unregister: false);
            }
        }
        public override async ValueTask Handle(P06CreateSession packet)
        {
            var response = Packets.New <P07CreateSessionResponse>();

            using var csp = SHA256.Create();
            byte[] passwordHash = csp.ComputeHash(packet.KeyHash);

            // As of RFC 5321 the local-part of an email address should not be case-sensitive.
            // EF Core converts the C# == operator to = in SQL which compares the contents of byte arrays
            var confirmation = await
                                   (from c in Database.MailConfirmations.AsQueryable().Where(c => c.MailAddress == packet.AccountName.ToLowerInvariant())
                                   join a in Database.Accounts.AsQueryable().Where(a => a.PasswordHash == passwordHash)
                                   on c.AccountId equals a.AccountId
                                   select c)
                               .SingleOrDefaultAsync().ConfigureAwait(false);

            if (confirmation == null)
            {
                response.StatusCode = CreateSessionStatus.InvalidCredentials;
                await Client.Send(response).ConfigureAwait(false);

                return;
            }
            if (confirmation.ConfirmationTime == default)
            {
                response.StatusCode = CreateSessionStatus.UnconfirmedAccount;
                await Client.Send(response).ConfigureAwait(false);

                return;
            }

            byte[] sessionToken     = SkynetRandom.Bytes(32);
            byte[] sessionTokenHash = csp.ComputeHash(sessionToken);
            string webToken         = SkynetRandom.String(30);

            byte[] webTokenHash = csp.ComputeHash(Encoding.UTF8.GetBytes(webToken));

            Session session = await Database.AddSession(new Session
            {
                AccountId             = confirmation.AccountId,
                SessionTokenHash      = sessionTokenHash,
                WebTokenHash          = webTokenHash,
                ApplicationIdentifier = Client.ApplicationIdentifier,
                LastConnected         = DateTime.Now,
                LastVersionCode       = Client.VersionCode,
                FcmToken = packet.FcmRegistrationToken
            }).ConfigureAwait(false);

            Message deviceList = await injector.CreateDeviceList(confirmation.AccountId).ConfigureAwait(false);

            Client.Authenticate(confirmation.AccountId, session.SessionId);

            response.StatusCode   = CreateSessionStatus.Success;
            response.AccountId    = session.AccountId;
            response.SessionId    = session.SessionId;
            response.SessionToken = sessionToken;
            response.WebToken     = webToken;
            await Client.Send(response).ConfigureAwait(false);

            await Delivery.StartSyncChannels(Client, new List <long>(), lastMessageId : default).ConfigureAwait(false);

            await Delivery.StartSendMessage(deviceList, null).ConfigureAwait(false);

            IClient old = connections.Add(Client);

            if (old != null)
            {
                _ = old.DisposeAsync(unregister: false);
            }
        }