public List <ITextChatMessage> GetHistory(RoomId roomId, List <Enumerables.MessageVisibility> withVisibilities, int messageCount) { using (var db = new HellolingoEntities()) { // [Replaced by a SPROC call to try to improve perf issues] var entityResult = db.TextChats.AsNoTracking() .OrderByDescending(a => a.ID) .Where(a => a.RoomId == roomId && withVisibilities.Any(b => (byte)b == a.Visibility)) // THIS NEXT LINE IS CRITICAL!!!! NOT USING MAKES THE QUERY WAY SLOWER, TO THE POINT THAT IT BRINGS // THE SERVER DOWN WHEN THE IIS APPLICATION POOL IS RECYCLED AND ALL USERS ARE RELOADING ALL THEIR ROOMS. // EF ACTUALLY LOADS THE FULL DEFINITION OF THE USER WHEN ToList IS CALLED... WHICH WILL CLEARLY TAKE A WHOLE LOT OF TIME. .Select(a => new { a.ID, a.When, a.UserId, a.FirstName, a.RoomId, a.Text, a.Visibility }) .Take(messageCount).ToList().OrderBy(a => a.ID); //var entityResult = db.TextChat_GetHistory(messageCount, roomId, string.Join(",", withVisibilities.Cast<int>())); return(entityResult.Select( msg => (ITextChatMessage) new TextChatMessage { When = msg.When, UserId = msg.UserId, FirstName = msg.FirstName, RoomId = msg.RoomId, Text = msg.Text, Visibility = (Enumerables.MessageVisibility)msg.Visibility }).OrderBy(msg => msg.When).ToList()); } }
public void AddMessageTest() { var storage = new TextChatDbStorage(); var message = new TextChatMessage { UserId = 1, FirstName = "Bernard", LastName = "V", RoomId = "english", Text = "AddMessageTest = Hello World!", Visibility = MessageVisibility.Everyone, DeviceTag = 0 }; storage.AddMessageAsync(message); // check last message DataAccess.TextChat savedMessage; using (var db = new HellolingoEntities()) { savedMessage = db.TextChats.OrderByDescending(a => a.ID).FirstOrDefault(); } Assert.IsNotNull(savedMessage); Assert.AreEqual(message.When, savedMessage.When); // ReSharper disable once PossibleInvalidOperationException Assert.AreEqual(message.UserId, new UserId(savedMessage.UserId.Value)); Assert.AreEqual(0, savedMessage.DeviceTag, "DeviceTag must be null"); Assert.AreEqual(message.FirstName, savedMessage.FirstName); Assert.AreEqual(message.RoomId.ToString(), savedMessage.RoomId); Assert.AreEqual(message.Text, savedMessage.Text); Assert.AreEqual((byte)message.Visibility, savedMessage.Visibility); }
public List <IPrivateChatStatus> GetPrivateChatStatuses(int userId) { using (var db = new HellolingoEntities()) { var entityResult = db.TextChatTrackers.AsNoTracking() .OrderByDescending(a => a.StatusAt) .Where(a => a.UserId == userId && a.Status != TrackerStatus.AutoBlocked) .Select(a => new { a.Status, a.StatusAt, a.Partner }) // IMPORTANT LINE: It prevents EF from having to load all related data (e.g. users, statuses details, etc...) .ToList(); return(entityResult.Select( status => (IPrivateChatStatus) new PrivateChatStatus { Partner = new TextChatUser { FirstName = status.Partner.FirstName, Id = status.Partner.Id, LastName = status.Partner.LastName, Country = status.Partner.CountryId, Location = status.Partner.Location, Gender = status.Partner.Gender, Age = AgeInYearsHelper.GetAgeFrom(status.Partner.BirthYear, status.Partner.BirthMonth), Knows = status.Partner.KnowsId, Learns = status.Partner.LearnsId, Knows2 = status.Partner.Knows2Id, Learns2 = status.Partner.Learns2Id }, StatusId = status.Status, StatusAt = status.StatusAt }).ToList()); } }
public IEnumerable <ListedUser> List(ListRequest request) { using (HellolingoEntities db = new HellolingoEntities()) { int?tag = null; if (request.IsSharedTalkMember) { tag = UserTags.FormerSharedTalkMember; } if (request.IsLivemochaMember) { tag = UserTags.LivemochaMember; } if (request.IsSharedLingoMember) { tag = UserTags.SharedLingoMember; } IEnumerable <ListedUser> listedMembers = db.ListedUsers_GetBy( count: null, belowId: request.BelowId, knows: request.KnownId, learns: request.LearnId, firstName: request.FirstName, lastName: request.LastName, country: null, location: null, minAge: null, maxAge: null, tag: tag ).ToList(); return(listedMembers); } }
//public string LocalUserCulture => User.Identity.GetClaims().UserCulture; public async Task <User> GetLocalUser() { using (var db = new HellolingoEntities()) { var localUserId = LocalUserId; return(await db.Users.AsNoTracking().Include(u => u.Status).FirstOrDefaultAsync(u => u.Id == localUserId)); } }
public async Task LinkDeviceToUser(long deviceTag, int userId) { // Store in database using (var db = new HellolingoEntities()) { db.UsersDevices.AddOrUpdate(new UsersDevice { DeviceTag = deviceTag, UserId = userId, LastIPV4 = 0L }); await db.SaveChangesAsync(); } }
// DISCLAIMER: THIS IS NOT A PROPER UNIT TEST // It accesses the database // It relies on pre-populated data in that database // But it's a good demo public void MailboxSprocsTest() { var userId1 = 1; var userId2 = 2; var db = new HellolingoEntities(); // Insert a new mail (that User1 sends to user2) db.Mails_Insert( regulationStatus: MailRegulationStatuses.AutoPass, // This means that the regulation has cleared this message: No manual step / moderation required fromId: userId1, // Who send the mail replyToMail: null, // Defines to which mailId this mail a directly reply to, if any toId: userId2, // Who receives the mail subject: null, // Subject can be ignored. It will be filled with the beginning of the message. message: "Hello, This is a mail demo. Bye bye!" ); // Check that user1 has the sent message in his mailbox var mailFor1 = db.Mails_GetList(userId1).FirstOrDefault(); // The right message should be the first one, because the list is ordered with latest first Assert.AreEqual(userId1, mailFor1.FromId); Assert.AreEqual("true", mailFor1.Lead); // Lead = true: It means that this message is the latest one of all the messages sent between user1 and user2 Assert.AreEqual(null, mailFor1.ReplyToMail); Assert.AreEqual(MailStatuses.Sent, mailFor1.Status); Assert.AreEqual("Hello, This is a mail demo. Bye bye!", mailFor1.Subject); // Subject should be the first 100 characters of message Assert.AreEqual(userId2, mailFor1.ToId); // Check that user2 has the received message in his mailbox var mailFor2 = db.Mails_GetList(userId2).FirstOrDefault(); // The right message should be the first one, because the list is ordered with latest first Assert.AreEqual(userId1, mailFor2.FromId); Assert.AreEqual("true", mailFor2.Lead); // Lead = true: It means that this message is the latest one of all the messages sent between user1 and user2 Assert.AreEqual(null, mailFor2.ReplyToMail); Assert.AreEqual(MailStatuses.New, mailFor2.Status); Assert.AreEqual("Hello, This is a mail demo. Bye bye!", mailFor2.Subject); // Subject should be the first 100 characters of message Assert.AreEqual(userId2, mailFor2.ToId); // Archive users emails var mails = db.Mails_GetList(userId1).ToList(); foreach (var mail in mails) { db.Mails_Archive(userId1, mail.Id); } mails = db.Mails_GetList(userId2).ToList(); foreach (var mail in mails) { db.Mails_Archive(userId2, mail.Id); } // Get the list for user1. It should be empty b/c all mails have been archived mails = db.Mails_GetList(userId1).ToList(); Assert.AreEqual(0, mails.Count(r => r.Status != MailStatuses.Archived)); }
public async Task <PublicUser> GetProfile(GetProfileRequest request) { using (HellolingoEntities db = new HellolingoEntities()) { User foundUser = await db.Users.FindAsync(request.Id); if (foundUser == null) { Log.Error(LogTag.UserNotFoundForGetProfileRequest, Request, new { request }); return(null); } return(new PublicUser(foundUser)); } }
/// <summary> /// Constructor which takes a db context and wires up the stores with default instances using the context /// </summary> /// <param name="context"></param> public ApplicationUserStore(HellolingoEntities context) { if (context == null) { throw new ArgumentNullException("context"); } Context = context; AutoSaveChanges = true; _userStore = new EntityStore <AspNetUser>(context); _roleStore = new EntityStore <AspNetRole>(context); _logins = Context.Set <AspNetUserLogin>( ); _userClaims = Context.Set <AspNetUserClaim>( ); //_userRoles = Context.Set<AspNetRole>( ); }
public async Task AddMessageAsync(ITextChatMessage msg) { using (var db = new HellolingoEntities()) { var record = new DataAccess.TextChat { When = msg.When, RoomId = msg.RoomId, UserId = msg.UserId, DeviceTag = msg.DeviceTag, FirstName = msg.FirstName, LastName = msg.LastName, Text = msg.Text, Visibility = (byte)msg.Visibility, }; db.TextChats.Add(record); await db.SaveChangesAsync(); } }
public static async Task <Result <bool> > JoinRoom(User user, RoomId roomId) { var result = Result <bool> .True; if (!roomId.IsPrivate()) { return(result); } int userIdEf = user.Id; string roomIdEf = roomId; // Casting named types into their base type because EF doesn't get it otherwise. int partnerId = ChatModel.PartnerIdFrom(roomId, user.Id); using (var db = new HellolingoEntities()) { var userTracker = db.TextChatTrackers.Find(userIdEf, roomIdEf); var partnerTracker = db.TextChatTrackers.Find(partnerId, roomIdEf); // Handle people directly joining by the url from outside the chat if (userTracker == null || partnerTracker == null) { await RequestPrivateChat(user, roomId, partnerId); result.Reports.AddReport(LogTag.ChatRequestAddedFromJoinRoom, new { userId = user.Id, roomId }); return(result); } // Set new statuses according to current status if ((userTracker.Status == TrackerStatus.Invited || userTracker.Status == TrackerStatus.IgnoredInvite) && partnerTracker.Status == TrackerStatus.Inviting) { userTracker.Status = TrackerStatus.AcceptedInvite; partnerTracker.Status = TrackerStatus.InviteAccepted; userTracker.StatusAt = partnerTracker.StatusAt = DateTime.Now; result.Reports = new LogReports(LogTag.ChatRequestAccepted); } else if (userTracker.Status == TrackerStatus.InviteAccepted) { userTracker.Status = TrackerStatus.SeenInviteResponse; userTracker.StatusAt = DateTime.Now; } await db.SaveChangesAsync(); } return(result); }
private void SaveLastVisit(string userName) { using (var db = new HellolingoEntities()) { var user = db.Users.FirstOrDefault(u => u.AspNetUser.UserName == userName); if (user != null) { user.LastVisit = DateTime.Now; } try { db.SaveChanges(); } catch (Exception e) { LogError(e); } } }
public static async Task <Result <bool> > MarkAllCaughtUp(UserId userId, RoomId roomId) { int userIdEf = userId; string roomIdEf = roomId; // Casting named types into their base type because EF doesn't get it otherwise. var result = Result <bool> .True; using (var db = new HellolingoEntities()) { var userRecord = db.TextChatTrackers.Find(userIdEf, roomIdEf); if (userRecord == null) { return(new Result <bool>(false, LogTag.UnexpectedTrackerStatus, new { method = "MarkAllCaughtUp", userId, roomId }, LogLevel.Error)); } if (userRecord.Status == TrackerStatus.AllCaughtUp || userRecord.Status == TrackerStatus.Inviting || userRecord.Status == TrackerStatus.Invited) { return(result); } userRecord.Status = TrackerStatus.AllCaughtUp; userRecord.StatusAt = DateTime.Now; await db.SaveChangesAsync(); } return(result); }
public static async Task <Result <bool> > IgnorePrivateChat(UserId userId, RoomId roomId, UserId partnerId) { int userIdEf = userId, partnerIdEf = partnerId; string roomIdEf = roomId; // Casting named types into their base type because EF doesn't get it otherwise. using (var db = new HellolingoEntities()) { var inviterRecord = db.TextChatTrackers.Find(partnerIdEf, roomIdEf); var inviteeRecord = db.TextChatTrackers.Find(userIdEf, roomIdEf); if (inviterRecord == null || inviteeRecord == null) { return(new Result <bool>(false, LogTag.IgnorePrivateChatMissingTrackerRecord, new { userId, roomId, partnerId }, LogLevel.Error)); } // Set record for invitee inviteeRecord.Status = TrackerStatus.IgnoredInvite; inviteeRecord.StatusAt = DateTime.Now; await db.SaveChangesAsync(); } return(Result <bool> .True); }
public void TestFind() { var db = new HellolingoEntities(); var result = db.ListedUsers_GetBy( //Andriy: I made count 100, because test throws exception. I don't know, whether this exception by intention or not. //Bernard: ^ Fixed: Entity Framework doesn't support default values for stored procedure parameters, so enforced it with a check in the stored procedure. count: null, belowId: null, knows: null, learns: null, firstName: null, lastName: null, country: null, location: null, minAge: null, maxAge: null, tag: null ); var list = result.ToList(); Assert.AreNotEqual(0, list.Count); }
public static async Task <Result <bool> > PostTo(UserId userId, RoomId roomId) { var result = Result <bool> .True; string roomIdEf = roomId; // Casting named types into their base type because EF doesn't get it otherwise. int partnerId = ChatModel.PartnerIdFrom(roomId, userId); using (var db = new HellolingoEntities()) { var partnerRecord = db.TextChatTrackers.Find(partnerId, roomIdEf); if (partnerRecord == null) { return(new Result <bool>(false, LogTag.UnexpectedTrackerStatus, new { method = "PostTo", userId, roomId }, LogLevel.Error)); } if (partnerRecord.Status == TrackerStatus.Invited || partnerRecord.Status == TrackerStatus.AutoBlocked || partnerRecord.Status == TrackerStatus.DeclinedInvite || partnerRecord.Status == TrackerStatus.IgnoredInvite || partnerRecord.Status == TrackerStatus.UnreadMessages) { return(new Result <bool>(true)); } partnerRecord.Status = TrackerStatus.UnreadMessages; partnerRecord.StatusAt = DateTime.Now; await db.SaveChangesAsync(); } return(result); }
public void TestLastVisitUpdated() { var user = new AspNetUser() { UserName = "******" }; var filter = new LastVisitFilter(new LastVisitHelper()); var filterContext = new ActionExecutingContext(); var fakeHttpContext = new Mock <HttpContextBase>(); var fakeIdentityMock = new Mock <IIdentity>(); fakeIdentityMock.Setup(i => i.IsAuthenticated).Returns(true); fakeIdentityMock.Setup(i => i.Name).Returns(user.UserName); fakeIdentityMock.SetupGet(i => i.Name).Returns(user.UserName); fakeHttpContext.SetupGet(t => t.User.Identity).Returns(fakeIdentityMock.Object); var controllerContext = new Mock <ControllerContext>(); controllerContext.Setup(t => t.HttpContext).Returns(fakeHttpContext.Object); filterContext.HttpContext = fakeHttpContext.Object; DateTime before; DateTime after; using (HellolingoEntities db = new HellolingoEntities()) { User userBefore = db.Users.FirstOrDefault(u => u.AspNetUser.UserName == user.UserName); before = userBefore.LastVisit.Value; } filter.OnActionExecuting(filterContext); using (HellolingoEntities db = new HellolingoEntities()) { User userAfter = db.Users.FirstOrDefault(u => u.AspNetUser.UserName == user.UserName); after = userAfter.LastVisit.Value; } Assert.IsTrue(after > before); }
public async Task TestGetMemberById() { User userSharedTalk; using (var db = new HellolingoEntities()) { userSharedTalk = await db.Users.FindAsync(1); } var controller = new MemberController(); controller.User = new GenericPrincipal(new ClaimsIdentity(new Claim [] { new Claim(CustomClaimTypes.UserId, userSharedTalk.Id.ToString()) }), null); var foundMember = await controller.GetProfile(new MemberController.GetProfileRequest { Id = 1 }); Assert.AreEqual(userSharedTalk.Id, foundMember.Id, $"{nameof(foundMember.Id)} is wrong."); Assert.AreEqual(userSharedTalk.FirstName, foundMember.FirstName, $"{nameof(foundMember.FirstName)} is wrong."); Assert.AreEqual(userSharedTalk.LastName, foundMember.LastName, $"{nameof(foundMember.LastName)} is wrong."); Assert.AreEqual(userSharedTalk.CountryId, foundMember.Country, $"{nameof(foundMember.Country)} is wrong."); Assert.AreEqual(userSharedTalk.Location, foundMember.Location, $"{nameof(foundMember.Location)} is wrong."); Assert.AreEqual(userSharedTalk.KnowsId, foundMember.Knows, $"{nameof(foundMember.Knows)} is wrong."); Assert.AreEqual(userSharedTalk.LearnsId, foundMember.Learns, $"{nameof(foundMember.Learns)} is wrong."); Assert.AreEqual(userSharedTalk.Introduction, foundMember.Introduction, $"{nameof(foundMember.Introduction)} is wrong."); Assert.AreEqual(new DateTime(userSharedTalk.BirthYear, userSharedTalk.BirthMonth, 1).GetAgeInYears(DateTime.Now), foundMember.Age, $"{nameof(foundMember.Age)} is wrong."); Assert.IsTrue(foundMember.IsSharedTalkMember); User userNewUser; using (var db = new HellolingoEntities()) { userNewUser = await db.Users.FindAsync(5870); } var controller2 = new MemberController(); controller.User = new GenericPrincipal(new ClaimsIdentity(new Claim [] { new Claim(CustomClaimTypes.UserId, userNewUser.Id.ToString()) }), null); var foundMember2 = await controller2.GetProfile(new MemberController.GetProfileRequest { Id = 5870 }); Assert.AreEqual(userNewUser.Id, foundMember2.Id, $"{nameof(foundMember2.Id)} is wrong."); Assert.AreEqual(userNewUser.FirstName, foundMember2.FirstName, $"{nameof(foundMember2.FirstName)} is wrong."); Assert.AreEqual(userNewUser.LastName, foundMember2.LastName, $"{nameof(foundMember2.LastName)} is wrong."); Assert.AreEqual(userNewUser.CountryId, foundMember2.Country, $"{nameof(foundMember2.Country)} is wrong."); Assert.AreEqual(userNewUser.Location, foundMember2.Location, $"{nameof(foundMember2.Location)} is wrong."); Assert.AreEqual(userNewUser.KnowsId, foundMember2.Knows, $"{nameof(foundMember2.Knows)} is wrong."); Assert.AreEqual(userNewUser.LearnsId, foundMember2.Learns, $"{nameof(foundMember2.Learns)} is wrong."); Assert.AreEqual(userNewUser.Introduction, foundMember2.Introduction, $"{nameof(foundMember2.Introduction)} is wrong."); Assert.AreEqual(new DateTime(userNewUser.BirthYear, userNewUser.BirthMonth, 1).GetAgeInYears(DateTime.Now), foundMember2.Age, $"{nameof(foundMember2.Age)} is wrong."); Assert.IsFalse(foundMember2.IsSharedTalkMember); var controller3 = new MemberController(); try { await controller3.GetProfile(new MemberController.GetProfileRequest { Id = 0 }); } catch (HttpException e) { Assert.AreEqual((int)HttpStatusCode.BadRequest, e.GetHttpCode()); } }
public ActionResult MadeByMembers() { using (var db = new HellolingoEntities()) ViewBag.membersCount = db.Users.Max(r => r.Id); return(PartialView()); }
public static async Task <Result <Propagate> > RequestPrivateChat(User user, RoomId roomId, UserId partnerId) { int partnerIdEf = partnerId; string roomIdEf = roomId; // Casting named types into their base type because EF doesn't get it otherwise. var toStatus = TrackerStatus.Invited; var propagate = true; using (var db = new HellolingoEntities()) { var inviterRecord = db.TextChatTrackers.Find(user.Id, roomIdEf); var inviteeRecord = db.TextChatTrackers.Find(partnerIdEf, roomIdEf); var partner = db.Users.Find(partnerIdEf); if (inviterRecord != null || inviteeRecord != null) { return(new Result <Propagate>(false, LogTag.RequestPrivateChatHasExistingRecord, new { user.Id, roomId, partnerId }, LogLevel.Error)); } // Check if it's a restricted invite var restricted = false; var userKnows = new List <byte?> { user.KnowsId, user.Knows2Id, user.Knows3Id }; var userLearns = new List <byte?> { user.LearnsId, user.Learns2Id, user.Learns3Id }; var isHelper = userKnows.Contains(partner.LearnsId) || (partner.Learns2Id != null && userKnows.Contains(partner.Learns2Id)) || (partner.Learns3Id != null && userKnows.Contains(partner.Learns3Id)); if (!WhitelistedMembers.Contains(user.Id) && !isHelper) { // Reset RestrictedMembers every hour, which allows them to send on restricted invite every hour if (DateTime.Now.Hour != RestrictionResetHour) { RestrictedMembers = new HashSet <UserId>(); RestrictionResetHour = DateTime.Now.Hour; } // Detect if the invite is restricted var partnerKnows = new List <byte?> { partner.KnowsId, partner.Knows2Id, partner.Knows3Id }; var partnerLearns = new List <byte?> { partner.LearnsId, partner.Learns2Id, partner.Learns3Id }; Func <InviteRule, bool> inviteCheck = control => control.FromGender == user.Gender && control.ToGender == partner.Gender && (control.FromKnows == null || userKnows.Contains(control.FromKnows)) && (control.ToKnows == null || partnerKnows.Contains(control.ToKnows)) && (control.ToLearns == null || partnerLearns.Contains(control.ToLearns)); // Mark restricted if it matches pattern of restricted invites if (RestictedInvites.Any(restrict => inviteCheck(restrict))) { restricted = true; } // Mark if users only match on native language if ((userKnows.Contains(partner.KnowsId) || (partner.Knows2Id != null && userKnows.Contains(partner.Knows2Id)) || (partner.Knows3Id != null && userKnows.Contains(partner.Knows3Id))) && !(userLearns.Contains(partner.KnowsId) || (partner.Knows2Id != null && userLearns.Contains(partner.Knows2Id)) || (partner.Knows3Id != null && userLearns.Contains(partner.Knows3Id))) && !(userKnows.Contains(partner.LearnsId) || (partner.Learns2Id != null && userKnows.Contains(partner.Learns2Id)) || (partner.Learns3Id != null && userKnows.Contains(partner.Learns3Id))) && !(userLearns.Contains(partner.LearnsId) || (partner.Learns2Id != null && userLearns.Contains(partner.Learns2Id)) || (partner.Learns3Id != null && userLearns.Contains(partner.Learns3Id))) ) { restricted = true; } // Derestrict if whitelisted if (WhitelistedInvites.Any(allow => inviteCheck(allow))) { restricted = false; } // If restricted, block it, unless it's the first one from this user. if (restricted) { if (RestrictedMembers.Contains(user.Id)) { toStatus = TrackerStatus.AutoBlocked; propagate = false; } else { RestrictedMembers.Add(user.Id); } } } // Set record for inviter db.TextChatTrackers.Add(new TextChatTracker { UserId = user.Id, RoomId = roomIdEf, PartnerId = partnerIdEf, Status = TrackerStatus.Inviting, StatusAt = DateTime.Now, Initiator = true }); // Set record for invitee db.TextChatTrackers.Add(new TextChatTracker { UserId = partnerIdEf, RoomId = roomIdEf, PartnerId = user.Id, Status = toStatus, StatusAt = DateTime.Now, Initiator = false }); await db.SaveChangesAsync(); } return(new Result <Propagate>(propagate)); }