Beispiel #1
0
 private static void ClearConnectedClients(IJabbrRepository repository)
 {
     try
     {
         repository.RemoveAllClients();
         repository.CommitChanges();
     }
     catch (Exception ex)
     {
         Elmah.ErrorLog.GetDefault(null).Log(new Error(ex));
     }
 }
Beispiel #2
0
        private static void ClearConnectedClients(IJabbrRepository repository)
        {
            try
            {
                foreach (var u in repository.Users)
                {
                    u.Status = (int)UserStatus.Offline;
                }

                repository.RemoveAllClients();
                repository.CommitChanges();
            }
            catch (Exception ex)
            {
                Elmah.ErrorLog.GetDefault(null).Log(new Error(ex));
            }
        }
Beispiel #3
0
        public void SetInviteCode(ChatUser user, ChatRoom room, string inviteCode)
        {
            EnsureOwner(user, room);
            if (!room.Private)
            {
                throw new InvalidOperationException("Only private rooms can have invite codes");
            }

            // Set the invite code and save
            room.InviteCode = inviteCode;
            _repository.CommitChanges();
        }
Beispiel #4
0
        public async Task <IActionResult> ChangeUsername(ChangeUsernameViewModel model)
        {
            if (!User.Identity.IsAuthenticated)
            {
                return(View(HttpStatusCode.Forbidden));
            }

            // HttpContextAccessor DI works when Singelton (Scoped injects null)
            var id = _context.HttpContext.User.GetUserId();

            ChatUser user        = _repository.GetUserById(id);
            string   oldUsername = user.Name; //user.UserName

            try
            {
                if (ModelState.IsValid)
                {
                    var result = await _signInManager.CheckPasswordSignInAsync(user, model.password, false);

                    if (result.Succeeded)
                    {
                        user.UserName = model.username;
                        user.Name     = model.username;
                        _repository.CommitChanges();

                        //  _notificationService.OnUserNameChanged(user, oldUsername, model.username);

                        return(RedirectToAction(nameof(Index), new { Message = ManageMessageId.ChangeUsernameSuccess }));
                    }
                    else
                    {
                        return(new RedirectResult(Url.Action("Index", new { Message = ManageMessageId.WrongPassword }) + "#changeUsername"));
                    }
                }
            }
            catch (Exception ex)
            {
                return(RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }));
            }

            return(new RedirectResult(Url.Action("Index", new { Message = ManageMessageId.ErrorChangeUsername }) + "#changeUsername"));
        }
Beispiel #5
0
        private ChatUser AddUser(string userName, string providerName, string identity, string email)
        {
            if (!IsValidUserName(userName))
            {
                throw new InvalidOperationException(String.Format("'{0}' is not a valid user name.", userName));
            }

            EnsureProviderAndIdentityAvailable(providerName, identity);

            // This method is used in the auth workflow. If the username is taken it will add a number
            // to the user name.
            if (UserExists(userName))
            {
                var usersWithNameLikeMine = _repository.Users.Count(u => u.Name.StartsWith(userName));
                userName += usersWithNameLikeMine;
            }

            var user = new ChatUser
            {
                Name         = userName,
                Status       = (int)UserStatus.Active,
                Hash         = email.ToMD5(),
                Id           = Guid.NewGuid().ToString("d"),
                LastActivity = DateTime.UtcNow,
                IsAdmin      = IsFirstUser()
            };

            var chatUserIdentity = new ChatUserIdentity
            {
                User         = user,
                Email        = email,
                Identity     = identity,
                ProviderName = providerName
            };

            _repository.Add(user);
            _repository.Add(chatUserIdentity);
            _repository.CommitChanges();

            return(user);
        }
Beispiel #6
0
        private void CheckUserStatus(ILogger logger, IJabbrRepository repo)
        {
            var inactiveUsers = new List <ChatUser>();

            IQueryable <ChatUser> users = repo.GetOnlineUsers().Where(u =>
                                                                      SqlFunctions.DateDiff("mi", u.LastActivity, DateTime.UtcNow) > 5);

            foreach (var user in users.ToList())
            {
                user.Status = (int)UserStatus.Inactive;
                inactiveUsers.Add(user);
            }

            if (inactiveUsers.Count > 0)
            {
                PerformRoomAction(inactiveUsers, async roomGroup =>
                {
                    await _hubContext.Clients.Group(roomGroup.Room.Name).markInactive(roomGroup.Users);
                });

                repo.CommitChanges();
            }
        }
Beispiel #7
0
        private void UpdatePresence(ILogger logger, IJabbrRepository repo)
        {
            // Get all connections on this node and update the activity
            foreach (var connection in _heartbeat.GetConnections())
            {
                if (!connection.IsAlive)
                {
                    continue;
                }

                ChatClient client = repo.GetClientById(connection.ConnectionId);

                if (client != null)
                {
                    client.LastActivity = DateTimeOffset.UtcNow;
                }
                else
                {
                    EnsureClientConnected(logger, repo, connection);
                }
            }

            repo.CommitChanges();
        }
Beispiel #8
0
        public void Join(bool reconnecting)
        {
            // Get the client state
            var userId = Context.User.GetUserId();

            // Try to get the user from the client state
            ChatUser user = _repository.GetUserById(userId);

            if (!reconnecting)
            {
                // Update some user values
                _service.UpdateActivity(user, Context.ConnectionId, UserAgent);
                _repository.CommitChanges();
            }

            ClientState clientState = GetClientState();

            OnUserInitialize(clientState, user, reconnecting);
        }
        private void RemoveOfflineUsers(ILogger logger, IJabbrRepository repo)
        {
            var offlineUsers = new List<ChatUser>();
            IQueryable<ChatUser> users = repo.GetOnlineUsers();

            foreach (var user in users.ToList())
            {
                if (user.ConnectedClients.Count == 0)
                {
                    logger.Log("{0} has no clients. Marking as offline", user.Name);

                    // Fix users that are marked as inactive but have no clients
                    user.Status = (int)UserStatus.Offline;
                    offlineUsers.Add(user);
                }
            }

            if (offlineUsers.Count > 0)
            {
                PerformRoomAction(offlineUsers, async roomGroup =>
                {
                    foreach (var user in roomGroup.Users)
                    {
                        await _hubContext.Clients.Group(roomGroup.Room.Name).leave(user, roomGroup.Room.Name);
                    }
                });

                repo.CommitChanges();
            }
        }
Beispiel #10
0
        // This is an uber hack to make sure the db is in sync with SignalR
        private void EnsureClientConnected(ILogger logger, IJabbrRepository repo, ITrackingConnection connection)
        {
            var contextField = connection.GetType().GetField("_context",
                                          BindingFlags.NonPublic | BindingFlags.Instance);
            if (contextField == null)
            {
                return;
            }

            var context = contextField.GetValue(connection) as HostContext;

            if (context == null)
            {
                return;
            }

            string connectionData = context.Request.QueryString["connectionData"];

            if (String.IsNullOrEmpty(connectionData))
            {
                return;
            }

            var hubs = JsonConvert.DeserializeObject<HubConnectionData[]>(connectionData);

            if (hubs.Length != 1)
            {
                return;
            }

            // We only care about the chat hub
            if (!hubs[0].Name.Equals("chat", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            logger.Log("Connection {0} exists but isn't tracked.", connection.ConnectionId);

            string userId = context.Request.User.GetUserId();

            ChatUser user = repo.GetUserById(userId);
            if (user == null)
            {
                logger.Log("Unable to find user with id {0}", userId);
                return;
            }

            var client = new ChatClient
            {
                Id = connection.ConnectionId,
                User = user,
                UserAgent = context.Request.Headers["User-Agent"],
                LastActivity = DateTimeOffset.UtcNow,
                LastClientActivity = user.LastActivity
            };

            repo.Add(client);
            repo.CommitChanges();
        }
Beispiel #11
0
        public AccountModule(IApplicationSettings applicationSettings,
                             IAuthenticationTokenService authenticationTokenService,
                             IMembershipService membershipService,
                             IJabbrRepository repository,
                             IAuthenticationService authService,
                             IChatNotificationService notificationService)
            : base("/account")
        {
            Get["/"] = _ =>
            {
                if (Context.CurrentUser == null)
                {
                    return HttpStatusCode.Forbidden;
                }

                ChatUser user = repository.GetUserById(Context.CurrentUser.UserName);

                return GetProfileView(authService, user);
            };

            Get["/login"] = _ =>
            {
                if (Context.CurrentUser != null)
                {
                    return Response.AsRedirect("~/");
                }

                return View["login", GetLoginViewModel(applicationSettings, repository, authService)];
            };

            Post["/login"] = param =>
            {
                if (Context.CurrentUser != null)
                {
                    return Response.AsRedirect("~/");
                }

                string username = Request.Form.username;
                string password = Request.Form.password;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", "Name is required");
                }

                if (String.IsNullOrEmpty(password))
                {
                    this.AddValidationError("password", "Password is required");
                }

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        ChatUser user = membershipService.AuthenticateUser(username, password);
                        return this.CompleteLogin(authenticationTokenService, user);
                    }
                    else
                    {
                        return View["login", GetLoginViewModel(applicationSettings, repository, authService)];
                    }
                }
                catch
                {
                    this.AddValidationError("_FORM", "Login failed. Check your username/password.");
                    return View["login", GetLoginViewModel(applicationSettings, repository, authService)];
                }
            };

            Post["/logout"] = _ =>
            {
                if (Context.CurrentUser == null)
                {
                    return HttpStatusCode.Forbidden;
                }

                var response = Response.AsJson(new { success = true });

                response.AddCookie(new NancyCookie(Constants.UserTokenCookie, null)
                {
                    Expires = DateTime.Now.AddDays(-1)
                });

                return response;
            };

            Get["/register"] = _ =>
            {
                if (Context.CurrentUser != null)
                {
                    return Response.AsRedirect("~/");
                }

                return View["register"];
            };

            Post["/create"] = _ =>
            {
                if (Context.CurrentUser != null)
                {
                    return Response.AsRedirect("~/");
                }

                string username = Request.Form.username;
                string email = Request.Form.email;
                string password = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", "Name is required");
                }

                if (String.IsNullOrEmpty(email))
                {
                    this.AddValidationError("email", "Email is required");
                }

                ValidatePassword(password, confirmPassword);

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        ChatUser user = membershipService.AddUser(username, email, password);
                        return this.CompleteLogin(authenticationTokenService, user);
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                return View["register"];
            };

            Post["/unlink"] = param =>
            {
                if (Context.CurrentUser == null)
                {
                    return HttpStatusCode.Forbidden;
                }

                string provider = Request.Form.provider;
                ChatUser user = repository.GetUserById(Context.CurrentUser.UserName);

                if (user.Identities.Count == 1 && !user.HasUserNameAndPasswordCredentials())
                {
                    this.AddAlertMessage("error", "You cannot unlink this account because you would lose your ability to login.");
                    return Response.AsRedirect("~/account/#identityProviders");
                }

                var identity = user.Identities.FirstOrDefault(i => i.ProviderName == provider);

                if (identity != null)
                {
                    repository.Remove(identity);

                    this.AddAlertMessage("success", String.Format("Successfully unlinked {0} account.", provider));
                    return Response.AsRedirect("~/account/#identityProviders");
                }

                return HttpStatusCode.BadRequest;
            };

            Post["/newpassword"] = _ =>
            {
                if (Context.CurrentUser == null)
                {
                    return HttpStatusCode.Forbidden;
                }

                string password = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Context.CurrentUser.UserName);

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.SetUserPassword(user, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    this.AddAlertMessage("success", "Successfully added a password.");
                    return Response.AsRedirect("~/account/#changePassword");
                }

                return GetProfileView(authService, user);
            };

            Post["/changepassword"] = _ =>
            {
                if (Context.CurrentUser == null)
                {
                    return HttpStatusCode.Forbidden;
                }

                string oldPassword = Request.Form.oldPassword;
                string password = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(oldPassword))
                {
                    this.AddValidationError("oldPassword", "Old password is required");
                }

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Context.CurrentUser.UserName);

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserPassword(user, oldPassword, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    this.AddAlertMessage("success", "Successfully changed your password.");
                    return Response.AsRedirect("~/account/#changePassword");
                }

                return GetProfileView(authService, user);
            };

            Post["/changeusername"] = _ =>
            {
                if (Context.CurrentUser == null)
                {
                    return HttpStatusCode.Forbidden;
                }

                string username = Request.Form.username;
                string confirmUsername = Request.Form.confirmUsername;

                ValidateUsername(username, confirmUsername);

                ChatUser user = repository.GetUserById(Context.CurrentUser.UserName);
                string oldUsername = user.Name;

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserName(user, username);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    notificationService.OnUserNameChanged(user, oldUsername, username);

                    this.AddAlertMessage("success", "Successfully changed your username.");
                    return Response.AsRedirect("~/account/#changeUsername");
                }

                return GetProfileView(authService, user);
            };
        }
Beispiel #12
0
        public void SetInviteCode(ChatUser user, ChatRoom room, string inviteCode)
        {
            EnsureOwnerOrAdmin(user, room);
            if (!room.Private)
            {
                throw new HubException(LanguageResources.InviteCode_PrivateRoomRequired);
            }

            // Set the invite code and save
            room.InviteCode = inviteCode;
            _repository.CommitChanges();
        }
Beispiel #13
0
        public AccountModule(ApplicationSettings applicationSettings,
                             IMembershipService membershipService,
                             IJabbrRepository repository,
                             IAuthenticationService authService,
                             IChatNotificationService notificationService,
                             IUserAuthenticator authenticator)
            : base("/account")
        {
            Get["/"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                return GetProfileView(authService, user);
            };

            Get["/login"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return Response.AsRedirect("~/");
                }

                return View["login", GetLoginViewModel(applicationSettings, repository, authService)];
            };

            Post["/login"] = param =>
            {
                if (IsAuthenticated)
                {
                    return Response.AsRedirect("~/");
                }

                string username = Request.Form.username;
                string password = Request.Form.password;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", "Name is required");
                }

                if (String.IsNullOrEmpty(password))
                {
                    this.AddValidationError("password", "Password is required");
                }

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        IList<Claim> claims;
                        if (authenticator.TryAuthenticateUser(username, password, out claims))
                        {
                            return this.SignIn(claims);
                        }
                    }
                }
                catch
                {
                    // Swallow the exception
                }

                this.AddValidationError("_FORM", "Login failed. Check your username/password.");

                return View["login", GetLoginViewModel(applicationSettings, repository, authService)];
            };

            Post["/logout"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                var response = Response.AsJson(new { success = true });

                this.SignOut();

                return response;
            };

            Get["/register"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return Response.AsRedirect("~/");
                }

                bool requirePassword = !Principal.Identity.IsAuthenticated;

                if (requirePassword &&
                    !applicationSettings.AllowUserRegistration)
                {
                    return HttpStatusCode.NotFound;
                }

                ViewBag.requirePassword = requirePassword;

                return View["register"];
            };

            Post["/create"] = _ =>
            {
                bool requirePassword = !Principal.Identity.IsAuthenticated;

                if (requirePassword &&
                    !applicationSettings.AllowUserRegistration)
                {
                    return HttpStatusCode.NotFound;
                }

                if (IsAuthenticated)
                {
                    return Response.AsRedirect("~/");
                }

                ViewBag.requirePassword = requirePassword;

                string username = Request.Form.username;
                string email = Request.Form.email;
                string password = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", "Name is required");
                }

                if (String.IsNullOrEmpty(email))
                {
                    this.AddValidationError("email", "Email is required");
                }

                try
                {
                    if (requirePassword)
                    {
                        ValidatePassword(password, confirmPassword);
                    }

                    if (ModelValidationResult.IsValid)
                    {
                        if (requirePassword)
                        {
                            ChatUser user = membershipService.AddUser(username, email, password);

                            return this.SignIn(user);
                        }
                        else
                        {
                            // Add the required claims to this identity
                            var identity = Principal.Identity as ClaimsIdentity;

                            if (!Principal.HasClaim(ClaimTypes.Name))
                            {
                                identity.AddClaim(new Claim(ClaimTypes.Name, username));
                            }

                            if (!Principal.HasClaim(ClaimTypes.Email))
                            {
                                identity.AddClaim(new Claim(ClaimTypes.Email, email));
                            }

                            return this.SignIn(Principal.Claims);
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                return View["register"];
            };

            Post["/unlink"] = param =>
            {
                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                string provider = Request.Form.provider;
                ChatUser user = repository.GetUserById(Principal.GetUserId());

                if (user.Identities.Count == 1 && !user.HasUserNameAndPasswordCredentials())
                {
                    Request.AddAlertMessage("error", "You cannot unlink this account because you would lose your ability to login.");
                    return Response.AsRedirect("~/account/#identityProviders");
                }

                var identity = user.Identities.FirstOrDefault(i => i.ProviderName == provider);

                if (identity != null)
                {
                    repository.Remove(identity);

                    Request.AddAlertMessage("success", String.Format("Successfully unlinked {0} account.", provider));
                    return Response.AsRedirect("~/account/#identityProviders");
                }

                return HttpStatusCode.BadRequest;
            };

            Post["/newpassword"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                string password = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.SetUserPassword(user, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    Request.AddAlertMessage("success", "Successfully added a password.");
                    return Response.AsRedirect("~/account/#changePassword");
                }

                return GetProfileView(authService, user);
            };

            Post["/changepassword"] = _ =>
            {
                if (!applicationSettings.AllowUserRegistration)
                {
                    return HttpStatusCode.NotFound;
                }

                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                string oldPassword = Request.Form.oldPassword;
                string password = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(oldPassword))
                {
                    this.AddValidationError("oldPassword", "Old password is required");
                }

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserPassword(user, oldPassword, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    Request.AddAlertMessage("success", "Successfully changed your password.");
                    return Response.AsRedirect("~/account/#changePassword");
                }

                return GetProfileView(authService, user);
            };

            Post["/changeusername"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                string username = Request.Form.username;
                string confirmUsername = Request.Form.confirmUsername;

                ValidateUsername(username, confirmUsername);

                ChatUser user = repository.GetUserById(Principal.GetUserId());
                string oldUsername = user.Name;

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserName(user, username);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    notificationService.OnUserNameChanged(user, oldUsername, username);

                    Request.AddAlertMessage("success", "Successfully changed your username.");
                    return Response.AsRedirect("~/account/#changeUsername");
                }

                return GetProfileView(authService, user);
            };
        }
Beispiel #14
0
        private static void ClearConnectedClients(IJabbrRepository repository)
        {
            try
            {
                foreach (var u in repository.Users)
                {
                    if (u.IsAfk)
                    {
                        u.Status = (int)UserStatus.Offline;
                    }
                }

                repository.RemoveAllClients();
                repository.CommitChanges();
            }
            catch (Exception ex)
            {
                Elmah.ErrorLog.GetDefault(null).Log(new Error(ex));
            }
        }
Beispiel #15
0
        public AccountModule(ApplicationSettings applicationSettings,
                             IMembershipService membershipService,
                             IJabbrRepository repository,
                             IAuthenticationService authService,
                             IChatNotificationService notificationService,
                             IUserAuthenticator authenticator,
                             IEmailService emailService)
            : base("/account")
        {
            Get["/"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                return GetProfileView(authService, user);
            };

            Get["/login"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return this.AsRedirectQueryStringOrDefault("~/");
                }

                return View["login", GetLoginViewModel(applicationSettings, repository, authService)];
            };

            Post["/login"] = param =>
            {
                if (!HasValidCsrfTokenOrSecHeader)
                {
                    return HttpStatusCode.Forbidden;
                }

                if (IsAuthenticated)
                {
                    return this.AsRedirectQueryStringOrDefault("~/");
                }

                string username = Request.Form.username;
                string password = Request.Form.password;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", LanguageResources.Authentication_NameRequired);
                }

                if (String.IsNullOrEmpty(password))
                {
                    this.AddValidationError("password", LanguageResources.Authentication_PassRequired);
                }

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        IList<Claim> claims;
                        if (authenticator.TryAuthenticateUser(username, password, out claims))
                        {
                            return this.SignIn(claims);
                        }
                    }
                }
                catch
                {
                    // Swallow the exception
                }

                this.AddValidationError("_FORM", LanguageResources.Authentication_GenericFailure);

                return View["login", GetLoginViewModel(applicationSettings, repository, authService)];
            };

            Post["/logout"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                var response = Response.AsJson(new { success = true });

                this.SignOut();

                return response;
            };

            Get["/register"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return this.AsRedirectQueryStringOrDefault("~/");
                }

                bool requirePassword = !Principal.Identity.IsAuthenticated;

                if (requirePassword &&
                    !applicationSettings.AllowUserRegistration)
                {
                    return HttpStatusCode.NotFound;
                }

                ViewBag.requirePassword = requirePassword;

                return View["register"];
            };

            Post["/create"] = _ =>
            {
                if (!HasValidCsrfTokenOrSecHeader)
                {
                    return HttpStatusCode.Forbidden;
                }

                bool requirePassword = !Principal.Identity.IsAuthenticated;

                if (requirePassword &&
                    !applicationSettings.AllowUserRegistration)
                {
                    return HttpStatusCode.NotFound;
                }

                if (IsAuthenticated)
                {
                    return this.AsRedirectQueryStringOrDefault("~/");
                }

                ViewBag.requirePassword = requirePassword;

                string username = Request.Form.username;
                string email = Request.Form.email;
                string password = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", LanguageResources.Authentication_NameRequired);
                }

                if (String.IsNullOrEmpty(email))
                {
                    this.AddValidationError("email", LanguageResources.Authentication_EmailRequired);
                }

                try
                {
                    if (requirePassword)
                    {
                        ValidatePassword(password, confirmPassword);
                    }

                    if (ModelValidationResult.IsValid)
                    {
                        if (requirePassword)
                        {
                            ChatUser user = membershipService.AddUser(username, email, password);

                            return this.SignIn(user);
                        }
                        else
                        {
                            // Add the required claims to this identity
                            var identity = Principal.Identity as ClaimsIdentity;

                            if (!Principal.HasClaim(ClaimTypes.Name))
                            {
                                identity.AddClaim(new Claim(ClaimTypes.Name, username));
                            }

                            if (!Principal.HasClaim(ClaimTypes.Email))
                            {
                                identity.AddClaim(new Claim(ClaimTypes.Email, email));
                            }

                            return this.SignIn(Principal.Claims);
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                return View["register"];
            };

            Post["/unlink"] = param =>
            {
                if (!HasValidCsrfTokenOrSecHeader)
                {
                    return HttpStatusCode.Forbidden;
                }

                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                string provider = Request.Form.provider;
                ChatUser user = repository.GetUserById(Principal.GetUserId());

                if (user.Identities.Count == 1 && !user.HasUserNameAndPasswordCredentials())
                {
                    Request.AddAlertMessage("error", LanguageResources.Account_UnlinkRequiresMultipleIdentities);
                    return Response.AsRedirect("~/account/#identityProviders");
                }

                var identity = user.Identities.FirstOrDefault(i => i.ProviderName == provider);

                if (identity != null)
                {
                    repository.Remove(identity);

                    Request.AddAlertMessage("success", String.Format(LanguageResources.Account_UnlinkCompleted, provider));
                    return Response.AsRedirect("~/account/#identityProviders");
                }

                return HttpStatusCode.BadRequest;
            };

            Post["/newpassword"] = _ =>
            {
                if (!HasValidCsrfTokenOrSecHeader)
                {
                    return HttpStatusCode.Forbidden;
                }

                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                string password = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.SetUserPassword(user, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    Request.AddAlertMessage("success", LanguageResources.Authentication_PassAddSuccess);
                    return Response.AsRedirect("~/account/#changePassword");
                }

                return GetProfileView(authService, user);
            };

            Post["/changepassword"] = _ =>
            {
                if (!HasValidCsrfTokenOrSecHeader)
                {
                    return HttpStatusCode.Forbidden;
                }

                if (!applicationSettings.AllowUserRegistration)
                {
                    return HttpStatusCode.NotFound;
                }

                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                string oldPassword = Request.Form.oldPassword;
                string password = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(oldPassword))
                {
                    this.AddValidationError("oldPassword", LanguageResources.Authentication_OldPasswordRequired);
                }

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserPassword(user, oldPassword, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    Request.AddAlertMessage("success", LanguageResources.Authentication_PassChangeSuccess);
                    return Response.AsRedirect("~/account/#changePassword");
                }

                return GetProfileView(authService, user);
            };

            Post["/changeusername"] = _ =>
            {
                if (!HasValidCsrfTokenOrSecHeader)
                {
                    return HttpStatusCode.Forbidden;
                }

                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                string username = Request.Form.username;
                string confirmUsername = Request.Form.confirmUsername;

                ValidateUsername(username, confirmUsername);

                ChatUser user = repository.GetUserById(Principal.GetUserId());
                string oldUsername = user.Name;

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserName(user, username);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    notificationService.OnUserNameChanged(user, oldUsername, username);

                    Request.AddAlertMessage("success", LanguageResources.Authentication_NameChangeCompleted);
                    return Response.AsRedirect("~/account/#changeUsername");
                }

                return GetProfileView(authService, user);
            };

            Get["/requestresetpassword"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return Response.AsRedirect("~/account/#changePassword");
                }

                if (!Principal.Identity.IsAuthenticated &&
                    !applicationSettings.AllowUserResetPassword ||
                    string.IsNullOrWhiteSpace(applicationSettings.EmailSender))
                {
                    return HttpStatusCode.NotFound;
                }

                return View["requestresetpassword"];
            };

            Post["/requestresetpassword"] = _ =>
            {
                if (!HasValidCsrfTokenOrSecHeader)
                {
                    return HttpStatusCode.Forbidden;
                }

                if (IsAuthenticated)
                {
                    return Response.AsRedirect("~/account/#changePassword");
                }

                if (!Principal.Identity.IsAuthenticated &&
                    !applicationSettings.AllowUserResetPassword ||
                    string.IsNullOrWhiteSpace(applicationSettings.EmailSender))
                {
                    return HttpStatusCode.NotFound;
                }

                string username = Request.Form.username;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", LanguageResources.Authentication_NameRequired);
                }

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        ChatUser user = repository.GetUserByName(username);

                        if (user == null)
                        {
                            this.AddValidationError("username", String.Format(LanguageResources.Account_NoMatchingUser, username));
                        }
                        else if (String.IsNullOrWhiteSpace(user.Email))
                        {
                            this.AddValidationError("username", String.Format(LanguageResources.Account_NoEmailForUser, username));
                        }
                        else
                        {
                            membershipService.RequestResetPassword(user, applicationSettings.RequestResetPasswordValidThroughInHours);
                            repository.CommitChanges();

                            emailService.SendRequestResetPassword(user, this.Request.Url.SiteBase + "/account/resetpassword/");

                            return View["requestresetpasswordsuccess", username];
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                return View["requestresetpassword"];
            };

            Get["/resetpassword/{id}"] = parameters =>
            {
                if (!applicationSettings.AllowUserResetPassword ||
                    string.IsNullOrWhiteSpace(applicationSettings.EmailSender))
                {
                    return HttpStatusCode.NotFound;
                }

                string resetPasswordToken = parameters.id;
                string userName = membershipService.GetUserNameFromToken(resetPasswordToken);

                // Is the token not valid, maybe some character change?
                if (userName == null)
                {
                    return View["resetpassworderror", LanguageResources.Account_ResetInvalidToken];
                }
                else
                {
                    ChatUser user = repository.GetUserByRequestResetPasswordId(userName, resetPasswordToken);

                    // Is the token expired?
                    if (user == null)
                    {
                        return View["resetpassworderror", LanguageResources.Account_ResetExpiredToken];
                    }
                    else
                    {
                        return View["resetpassword", user.RequestPasswordResetId];
                    }
                }
            };

            Post["/resetpassword/{id}"] = parameters =>
            {
                if (!HasValidCsrfTokenOrSecHeader)
                {
                    return HttpStatusCode.Forbidden;
                }

                if (!applicationSettings.AllowUserResetPassword ||
                    string.IsNullOrWhiteSpace(applicationSettings.EmailSender))
                {
                    return HttpStatusCode.NotFound;
                }

                string resetPasswordToken = parameters.id;
                string newPassword = Request.Form.password;
                string confirmNewPassword = Request.Form.confirmPassword;

                ValidatePassword(newPassword, confirmNewPassword);

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        string userName = membershipService.GetUserNameFromToken(resetPasswordToken);
                        ChatUser user = repository.GetUserByRequestResetPasswordId(userName, resetPasswordToken);

                        // Is the token expired?
                        if (user == null)
                        {
                            return View["resetpassworderror", LanguageResources.Account_ResetExpiredToken];
                        }
                        else
                        {
                            membershipService.ResetUserPassword(user, newPassword);
                            repository.CommitChanges();

                            return View["resetpasswordsuccess"];
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                return View["resetpassword", resetPasswordToken];
            };
        }
Beispiel #16
0
        public AccountModule(ApplicationSettings applicationSettings,
                             IMembershipService membershipService,
                             IJabbrRepository repository,
                             IAuthenticationService authService,
                             IChatNotificationService notificationService,
                             IUserAuthenticator authenticator)
            : base("/account")
        {
            Get["/"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                return(GetProfileView(authService, user));
            };

            Get["/login"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return(Response.AsRedirect("~/"));
                }

                return(View["login", GetLoginViewModel(applicationSettings, repository, authService)]);
            };

            Post["/login"] = param =>
            {
                if (IsAuthenticated)
                {
                    return(Response.AsRedirect("~/"));
                }

                string username = Request.Form.username;
                string password = Request.Form.password;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", "Name is required");
                }

                if (String.IsNullOrEmpty(password))
                {
                    this.AddValidationError("password", "Password is required");
                }

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        IList <Claim> claims;
                        if (authenticator.TryAuthenticateUser(username, password, out claims))
                        {
                            return(this.SignIn(claims));
                        }
                    }
                }
                catch
                {
                    // Swallow the exception
                }

                this.AddValidationError("_FORM", "Login failed. Check your username/password.");

                return(View["login", GetLoginViewModel(applicationSettings, repository, authService)]);
            };

            Post["/logout"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                var response = Response.AsJson(new { success = true });

                this.SignOut();

                return(response);
            };

            Get["/register"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return(Response.AsRedirect("~/"));
                }

                bool requirePassword = !Principal.Identity.IsAuthenticated;

                if (requirePassword &&
                    !applicationSettings.AllowUserRegistration)
                {
                    return(HttpStatusCode.NotFound);
                }

                ViewBag.requirePassword = requirePassword;

                return(View["register"]);
            };

            Post["/create"] = _ =>
            {
                bool requirePassword = !Principal.Identity.IsAuthenticated;

                if (requirePassword &&
                    !applicationSettings.AllowUserRegistration)
                {
                    return(HttpStatusCode.NotFound);
                }

                if (IsAuthenticated)
                {
                    return(Response.AsRedirect("~/"));
                }

                ViewBag.requirePassword = requirePassword;

                string username        = Request.Form.username;
                string email           = Request.Form.email;
                string password        = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", "Name is required");
                }

                if (String.IsNullOrEmpty(email))
                {
                    this.AddValidationError("email", "Email is required");
                }

                try
                {
                    if (requirePassword)
                    {
                        ValidatePassword(password, confirmPassword);
                    }

                    if (ModelValidationResult.IsValid)
                    {
                        if (requirePassword)
                        {
                            ChatUser user = membershipService.AddUser(username, email, password);

                            return(this.SignIn(user));
                        }
                        else
                        {
                            // Add the required claims to this identity
                            var identity = Principal.Identity as ClaimsIdentity;

                            if (!Principal.HasClaim(ClaimTypes.Name))
                            {
                                identity.AddClaim(new Claim(ClaimTypes.Name, username));
                            }

                            if (!Principal.HasClaim(ClaimTypes.Email))
                            {
                                identity.AddClaim(new Claim(ClaimTypes.Email, email));
                            }

                            return(this.SignIn(Principal.Claims));
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                return(View["register"]);
            };

            Post["/unlink"] = param =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string   provider = Request.Form.provider;
                ChatUser user     = repository.GetUserById(Principal.GetUserId());

                if (user.Identities.Count == 1 && !user.HasUserNameAndPasswordCredentials())
                {
                    Request.AddAlertMessage("error", "You cannot unlink this account because you would lose your ability to login.");
                    return(Response.AsRedirect("~/account/#identityProviders"));
                }

                var identity = user.Identities.FirstOrDefault(i => i.ProviderName == provider);

                if (identity != null)
                {
                    repository.Remove(identity);

                    Request.AddAlertMessage("success", String.Format("Successfully unlinked {0} account.", provider));
                    return(Response.AsRedirect("~/account/#identityProviders"));
                }

                return(HttpStatusCode.BadRequest);
            };

            Post["/newpassword"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string password        = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.SetUserPassword(user, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    Request.AddAlertMessage("success", "Successfully added a password.");
                    return(Response.AsRedirect("~/account/#changePassword"));
                }

                return(GetProfileView(authService, user));
            };

            Post["/changepassword"] = _ =>
            {
                if (!applicationSettings.AllowUserRegistration)
                {
                    return(HttpStatusCode.NotFound);
                }

                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string oldPassword     = Request.Form.oldPassword;
                string password        = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(oldPassword))
                {
                    this.AddValidationError("oldPassword", "Old password is required");
                }

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserPassword(user, oldPassword, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    Request.AddAlertMessage("success", "Successfully changed your password.");
                    return(Response.AsRedirect("~/account/#changePassword"));
                }

                return(GetProfileView(authService, user));
            };

            Post["/changeusername"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string username        = Request.Form.username;
                string confirmUsername = Request.Form.confirmUsername;

                ValidateUsername(username, confirmUsername);

                ChatUser user        = repository.GetUserById(Principal.GetUserId());
                string   oldUsername = user.Name;

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserName(user, username);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    notificationService.OnUserNameChanged(user, oldUsername, username);

                    Request.AddAlertMessage("success", "Successfully changed your username.");
                    return(Response.AsRedirect("~/account/#changeUsername"));
                }

                return(GetProfileView(authService, user));
            };
        }
Beispiel #17
0
        public NotificationsModule(IJabbrRepository repository,
                                   IChatService chatService,
                                   IChatNotificationService notificationService)
            : base("/notifications")
        {
            Get["/"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return Response.AsRedirect(String.Format("~/account/login?returnUrl={0}", HttpUtility.UrlEncode(Request.Path)));
                }

                var request = this.Bind<NotificationRequestModel>();

                ChatUser user = repository.GetUserById(Principal.GetUserId());
                int unreadCount = repository.GetUnreadNotificationsCount(user);
                IPagedList<NotificationViewModel> notifications = GetNotifications(repository, user, all: request.All, page: request.Page, roomName: request.Room);

                var viewModel = new NotificationsViewModel
                {
                    ShowAll = request.All,
                    UnreadCount = unreadCount,
                    Notifications = notifications,
                    DebugMode = (bool)Context.Items["_debugMode"],
                };

                return View["index", viewModel];
            };

            Post["/markasread"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                int notificationId = Request.Form.notificationId;

                Notification notification = repository.GetNotificationById(notificationId);

                if (notification == null)
                {
                    return HttpStatusCode.NotFound;
                }

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                if (notification.UserKey != user.Key)
                {
                    return HttpStatusCode.Forbidden;
                }

                notification.Read = true;
                repository.CommitChanges();

                notificationService.MessageReadStateChanged(user, notification.Message, notification);
                UpdateUnreadCountInChat(repository, notificationService, user);

                var response = Response.AsJson(new { success = true });

                return response;
            };

            Post["/markallasread"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return HttpStatusCode.Forbidden;
                }

                ChatUser user = repository.GetUserById(Principal.GetUserId());
                IList<Notification> unReadNotifications = repository.GetNotificationsByUser(user).Unread().ToList();

                if (!unReadNotifications.Any())
                {
                    return HttpStatusCode.NotFound;
                }

                foreach (var notification in unReadNotifications)
                {
                    notification.Read = true;
                    notificationService.MessageReadStateChanged(user, notification.Message, notification);
                }

                repository.CommitChanges();

                UpdateUnreadCountInChat(repository, notificationService, user);

                var response = Response.AsJson(new { success = true });

                return response;
            };

            Get["/{key}"] = _ =>
            {
                if (!IsAuthenticated)
                    return Response.AsRedirect(String.Format("~/account/login?returnUrl={0}", HttpUtility.UrlEncode(Request.Path)));

                var notification = repository.GetNotificationById(_.key);
                if (notification == null)
                    return HttpStatusCode.NotFound;

                var user = repository.GetUserById(Principal.GetUserId());
                if (notification.UserKey != user.Key)
                    return HttpStatusCode.Forbidden;

                var model = new {
                    DebugMode = (bool)Context.Items["_debugMode"],
                    Notification = notification
                };

                return View["view", model];
            };
        }
Beispiel #18
0
        public AccountModule(ApplicationSettings applicationSettings,
                             IMembershipService membershipService,
                             IJabbrRepository repository,
                             IAuthenticationService authService,
                             IChatNotificationService notificationService,
                             IUserAuthenticator authenticator,
                             IEmailService emailService)
            : base("/account")
        {
            Get["/"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                return(GetProfileView(authService, user));
            };

            Get["/login"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return(this.AsRedirectQueryStringOrDefault("~/"));
                }

                return(View["login", GetLoginViewModel(applicationSettings, repository, authService)]);
            };

            Post["/login"] = param =>
            {
                if (IsAuthenticated)
                {
                    return(this.AsRedirectQueryStringOrDefault("~/"));
                }

                string username = Request.Form.username;
                string password = Request.Form.password;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", LanguageResources.Authentication_NameRequired);
                }

                if (String.IsNullOrEmpty(password))
                {
                    this.AddValidationError("password", LanguageResources.Authentication_PassRequired);
                }

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        IList <Claim> claims;
                        if (authenticator.TryAuthenticateUser(username, password, out claims))
                        {
                            return(this.SignIn(claims));
                        }
                    }
                }
                catch
                {
                    // Swallow the exception
                }

                this.AddValidationError("_FORM", LanguageResources.Authentication_GenericFailure);

                return(View["login", GetLoginViewModel(applicationSettings, repository, authService)]);
            };

            Post["/logout"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                var response = Response.AsJson(new { success = true });

                this.SignOut();

                return(response);
            };

            Get["/register"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return(this.AsRedirectQueryStringOrDefault("~/"));
                }

                bool requirePassword = !Principal.Identity.IsAuthenticated;

                if (requirePassword &&
                    !applicationSettings.AllowUserRegistration)
                {
                    return(HttpStatusCode.NotFound);
                }

                ViewBag.requirePassword = requirePassword;

                return(View["register"]);
            };

            Post["/create"] = _ =>
            {
                bool requirePassword = !Principal.Identity.IsAuthenticated;

                if (requirePassword &&
                    !applicationSettings.AllowUserRegistration)
                {
                    return(HttpStatusCode.NotFound);
                }

                if (IsAuthenticated)
                {
                    return(this.AsRedirectQueryStringOrDefault("~/"));
                }

                ViewBag.requirePassword = requirePassword;

                string username        = Request.Form.username;
                string email           = Request.Form.email;
                string password        = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", LanguageResources.Authentication_NameRequired);
                }

                if (String.IsNullOrEmpty(email))
                {
                    this.AddValidationError("email", LanguageResources.Authentication_EmailRequired);
                }

                try
                {
                    if (requirePassword)
                    {
                        ValidatePassword(password, confirmPassword);
                    }

                    if (ModelValidationResult.IsValid)
                    {
                        if (requirePassword)
                        {
                            ChatUser user = membershipService.AddUser(username, email, password);

                            return(this.SignIn(user));
                        }
                        else
                        {
                            // Add the required claims to this identity
                            var identity = Principal.Identity as ClaimsIdentity;

                            if (!Principal.HasClaim(ClaimTypes.Name))
                            {
                                identity.AddClaim(new Claim(ClaimTypes.Name, username));
                            }

                            if (!Principal.HasClaim(ClaimTypes.Email))
                            {
                                identity.AddClaim(new Claim(ClaimTypes.Email, email));
                            }

                            return(this.SignIn(Principal.Claims));
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                return(View["register"]);
            };

            Post["/unlink"] = param =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string   provider = Request.Form.provider;
                ChatUser user     = repository.GetUserById(Principal.GetUserId());

                if (user.Identities.Count == 1 && !user.HasUserNameAndPasswordCredentials())
                {
                    Request.AddAlertMessage("error", LanguageResources.Account_UnlinkRequiresMultipleIdentities);
                    return(Response.AsRedirect("~/account/#identityProviders"));
                }

                var identity = user.Identities.FirstOrDefault(i => i.ProviderName == provider);

                if (identity != null)
                {
                    repository.Remove(identity);

                    Request.AddAlertMessage("success", String.Format(LanguageResources.Account_UnlinkCompleted, provider));
                    return(Response.AsRedirect("~/account/#identityProviders"));
                }

                return(HttpStatusCode.BadRequest);
            };

            Post["/newpassword"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string password        = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.SetUserPassword(user, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    Request.AddAlertMessage("success", LanguageResources.Authentication_PassAddSuccess);
                    return(Response.AsRedirect("~/account/#changePassword"));
                }

                return(GetProfileView(authService, user));
            };

            Post["/changepassword"] = _ =>
            {
                if (!applicationSettings.AllowUserRegistration)
                {
                    return(HttpStatusCode.NotFound);
                }

                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string oldPassword     = Request.Form.oldPassword;
                string password        = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(oldPassword))
                {
                    this.AddValidationError("oldPassword", LanguageResources.Authentication_OldPasswordRequired);
                }

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserPassword(user, oldPassword, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    Request.AddAlertMessage("success", LanguageResources.Authentication_PassChangeSuccess);
                    return(Response.AsRedirect("~/account/#changePassword"));
                }

                return(GetProfileView(authService, user));
            };

            Post["/changeusername"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string username        = Request.Form.username;
                string confirmUsername = Request.Form.confirmUsername;

                ValidateUsername(username, confirmUsername);

                ChatUser user        = repository.GetUserById(Principal.GetUserId());
                string   oldUsername = user.Name;

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserName(user, username);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    notificationService.OnUserNameChanged(user, oldUsername, username);

                    Request.AddAlertMessage("success", LanguageResources.Authentication_NameChangeCompleted);
                    return(Response.AsRedirect("~/account/#changeUsername"));
                }

                return(GetProfileView(authService, user));
            };

            Get["/requestresetpassword"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return(Response.AsRedirect("~/account/#changePassword"));
                }

                if (!Principal.Identity.IsAuthenticated &&
                    !applicationSettings.AllowUserResetPassword ||
                    string.IsNullOrWhiteSpace(applicationSettings.EmailSender))
                {
                    return(HttpStatusCode.NotFound);
                }

                return(View["requestresetpassword"]);
            };

            Post["/requestresetpassword"] = _ =>
            {
                if (IsAuthenticated)
                {
                    return(Response.AsRedirect("~/account/#changePassword"));
                }

                if (!Principal.Identity.IsAuthenticated &&
                    !applicationSettings.AllowUserResetPassword ||
                    string.IsNullOrWhiteSpace(applicationSettings.EmailSender))
                {
                    return(HttpStatusCode.NotFound);
                }

                string username = Request.Form.username;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", LanguageResources.Authentication_NameRequired);
                }

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        ChatUser user = repository.GetUserByName(username);

                        if (user == null)
                        {
                            this.AddValidationError("username", String.Format(LanguageResources.Account_NoMatchingUser, username));
                        }
                        else if (String.IsNullOrWhiteSpace(user.Email))
                        {
                            this.AddValidationError("username", String.Format(LanguageResources.Account_NoEmailForUser, username));
                        }
                        else
                        {
                            membershipService.RequestResetPassword(user, applicationSettings.RequestResetPasswordValidThroughInHours);
                            repository.CommitChanges();

                            emailService.SendRequestResetPassword(user, this.Request.Url.SiteBase + "/account/resetpassword/");

                            return(View["requestresetpasswordsuccess", username]);
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                return(View["requestresetpassword"]);
            };

            Get["/resetpassword/{id}"] = parameters =>
            {
                if (!applicationSettings.AllowUserResetPassword ||
                    string.IsNullOrWhiteSpace(applicationSettings.EmailSender))
                {
                    return(HttpStatusCode.NotFound);
                }

                string resetPasswordToken = parameters.id;
                string userName           = membershipService.GetUserNameFromToken(resetPasswordToken);

                // Is the token not valid, maybe some character change?
                if (userName == null)
                {
                    return(View["resetpassworderror", LanguageResources.Account_ResetInvalidToken]);
                }
                else
                {
                    ChatUser user = repository.GetUserByRequestResetPasswordId(userName, resetPasswordToken);

                    // Is the token expired?
                    if (user == null)
                    {
                        return(View["resetpassworderror", LanguageResources.Account_ResetExpiredToken]);
                    }
                    else
                    {
                        return(View["resetpassword", user.RequestPasswordResetId]);
                    }
                }
            };

            Post["/resetpassword/{id}"] = parameters =>
            {
                if (!applicationSettings.AllowUserResetPassword ||
                    string.IsNullOrWhiteSpace(applicationSettings.EmailSender))
                {
                    return(HttpStatusCode.NotFound);
                }

                string resetPasswordToken = parameters.id;
                string newPassword        = Request.Form.password;
                string confirmNewPassword = Request.Form.confirmPassword;

                ValidatePassword(newPassword, confirmNewPassword);

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        string   userName = membershipService.GetUserNameFromToken(resetPasswordToken);
                        ChatUser user     = repository.GetUserByRequestResetPasswordId(userName, resetPasswordToken);

                        // Is the token expired?
                        if (user == null)
                        {
                            return(View["resetpassworderror", LanguageResources.Account_ResetExpiredToken]);
                        }
                        else
                        {
                            membershipService.ResetUserPassword(user, newPassword);
                            repository.CommitChanges();

                            return(View["resetpasswordsuccess"]);
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                return(View["resetpassword", resetPasswordToken]);
            };
        }
        public void ResponseSignIn(CookieResponseSignInContext context)
        {
            var authResult = new AuthenticationResult
            {
                Success = true
            };

            ChatUser loggedInUser = GetLoggedInUser(context);

            var principal = new ClaimsPrincipal(context.Identity);

            // Do nothing if it's authenticated
            if (principal.IsAuthenticated())
            {
                EnsurePersistentCookie(context);
                return;
            }

            ChatUser user = _repository.GetUser(principal);

            authResult.ProviderName = principal.GetIdentityProvider();

            // The user exists so add the claim
            if (user != null)
            {
                if (loggedInUser != null && user != loggedInUser)
                {
                    // Set an error message
                    authResult.Message = String.Format(LanguageResources.Account_AccountAlreadyLinked, authResult.ProviderName);
                    authResult.Success = false;

                    // Keep the old user logged in
                    context.Identity.AddClaim(new Claim(JabbRClaimTypes.Identifier, loggedInUser.Id));
                }
                else
                {
                    // Login this user
                    AddClaim(context, user);
                }
            }
            else if (principal.HasRequiredClaims())
            {
                ChatUser targetUser = null;

                // The user doesn't exist but the claims to create the user do exist
                if (loggedInUser == null)
                {
                    // New user so add them
                    user = _membershipService.AddUser(principal);

                    targetUser = user;
                }
                else
                {
                    // If the user is logged in then link
                    _membershipService.LinkIdentity(loggedInUser, principal);

                    _repository.CommitChanges();

                    authResult.Message = String.Format(LanguageResources.Account_AccountLinkedSuccess, authResult.ProviderName);

                    targetUser = loggedInUser;
                }

                AddClaim(context, targetUser);
            }
            else if (!principal.HasPartialIdentity())
            {
                // A partial identity means the user needs to add more claims to login
                context.Identity.AddClaim(new Claim(JabbRClaimTypes.PartialIdentity, "true"));
            }

            var cookieOptions = new CookieOptions
            {
                HttpOnly = true
            };

            context.Response.Cookies.Append(Constants.AuthResultCookie,
                                            JsonConvert.SerializeObject(authResult),
                                            cookieOptions);
        }
Beispiel #20
0
        private void CheckUserStatus(ILogger logger, IJabbrRepository repo)
        {
            var inactiveUsers = new List<ChatUser>();

            IQueryable<ChatUser> users = repo.GetOnlineUsers().Where(u =>
                SqlFunctions.DateDiff("mi", u.LastActivity, DateTime.UtcNow) > 5);

            foreach (var user in users.ToList())
            {
                user.Status = (int)UserStatus.Inactive;
                inactiveUsers.Add(user);
            }

            if (inactiveUsers.Count > 0)
            {
                PerformRoomAction(inactiveUsers, async roomGroup =>
                {
                    await _hubContext.Clients.Group(roomGroup.Room.Name).markInactive(roomGroup.Users);
                });

                repo.CommitChanges();
            }
        }
Beispiel #21
0
        // This is an uber hack to make sure the db is in sync with SignalR
        private void EnsureClientConnected(ILogger logger, IJabbrRepository repo, ITrackingConnection connection)
        {
            var contextField = connection.GetType().GetField("_context",
                                                             BindingFlags.NonPublic | BindingFlags.Instance);

            if (contextField == null)
            {
                return;
            }

            var context = contextField.GetValue(connection) as HostContext;

            if (context == null)
            {
                return;
            }

            string connectionData = context.Request.QueryString["connectionData"];

            if (String.IsNullOrEmpty(connectionData))
            {
                return;
            }

            var hubs = JsonConvert.DeserializeObject <HubConnectionData[]>(connectionData);

            if (hubs.Length != 1)
            {
                return;
            }

            // We only care about the chat hub
            if (!hubs[0].Name.Equals("chat", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            logger.Log("Connection {0} exists but isn't tracked.", connection.ConnectionId);

            string userId = context.Request.User.GetUserId();

            ChatUser user = repo.GetUserById(userId);

            if (user == null)
            {
                logger.Log("Unable to find user with id {0}", userId);
                return;
            }

            var client = new ChatClient
            {
                Id                 = connection.ConnectionId,
                User               = user,
                UserAgent          = context.Request.Headers["User-Agent"],
                LastActivity       = DateTimeOffset.UtcNow,
                LastClientActivity = user.LastActivity
            };

            repo.Add(client);
            repo.CommitChanges();
        }
Beispiel #22
0
        private void UpdatePresence(ILogger logger, IJabbrRepository repo)
        {
            // Get all connections on this node and update the activity
            foreach (var connection in _heartbeat.GetConnections())
            {
                if (!connection.IsAlive)
                {
                    continue;
                }

                ChatClient client = repo.GetClientById(connection.ConnectionId);

                if (client != null)
                {
                    client.LastActivity = DateTimeOffset.UtcNow;
                }
                else
                {
                    EnsureClientConnected(logger, repo, connection);
                }
            }

            repo.CommitChanges();
        }
Beispiel #23
0
        public AccountModule(IApplicationSettings applicationSettings,
                             IAuthenticationTokenService authenticationTokenService,
                             IMembershipService membershipService,
                             IJabbrRepository repository,
                             IAuthenticationService authService,
                             IChatNotificationService notificationService)
            : base("/account")
        {
            Get["/"] = _ =>
            {
                if (Context.CurrentUser == null)
                {
                    return(HttpStatusCode.Forbidden);
                }

                ChatUser user = repository.GetUserById(Context.CurrentUser.UserName);

                return(GetProfileView(authService, user));
            };

            Get["/login"] = _ =>
            {
                if (Context.CurrentUser != null)
                {
                    return(Response.AsRedirect("~/"));
                }

                return(View["login", GetLoginViewModel(applicationSettings, repository, authService)]);
            };

            Post["/login"] = param =>
            {
                if (Context.CurrentUser != null)
                {
                    return(Response.AsRedirect("~/"));
                }

                string username = Request.Form.username;
                string password = Request.Form.password;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", "Name is required");
                }

                if (String.IsNullOrEmpty(password))
                {
                    this.AddValidationError("password", "Password is required");
                }

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        ChatUser user = membershipService.AuthenticateUser(username, password);
                        return(this.CompleteLogin(authenticationTokenService, user));
                    }
                    else
                    {
                        return(View["login", GetLoginViewModel(applicationSettings, repository, authService)]);
                    }
                }
                catch
                {
                    this.AddValidationError("_FORM", "Login failed. Check your username/password.");
                    return(View["login", GetLoginViewModel(applicationSettings, repository, authService)]);
                }
            };

            Post["/logout"] = _ =>
            {
                if (Context.CurrentUser == null)
                {
                    return(HttpStatusCode.Forbidden);
                }

                var response = Response.AsJson(new { success = true });

                response.AddCookie(new NancyCookie(Constants.UserTokenCookie, null)
                {
                    Expires = DateTime.Now.AddDays(-1)
                });

                return(response);
            };

            Get["/register"] = _ =>
            {
                if (Context.CurrentUser != null)
                {
                    return(Response.AsRedirect("~/"));
                }

                return(View["register"]);
            };

            Post["/create"] = _ =>
            {
                if (Context.CurrentUser != null)
                {
                    return(Response.AsRedirect("~/"));
                }

                string username        = Request.Form.username;
                string email           = Request.Form.email;
                string password        = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(username))
                {
                    this.AddValidationError("username", "Name is required");
                }

                if (String.IsNullOrEmpty(email))
                {
                    this.AddValidationError("email", "Email is required");
                }

                ValidatePassword(password, confirmPassword);

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        ChatUser user = membershipService.AddUser(username, email, password);
                        return(this.CompleteLogin(authenticationTokenService, user));
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                return(View["register"]);
            };

            Post["/unlink"] = param =>
            {
                if (Context.CurrentUser == null)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string   provider = Request.Form.provider;
                ChatUser user     = repository.GetUserById(Context.CurrentUser.UserName);

                if (user.Identities.Count == 1 && !user.HasUserNameAndPasswordCredentials())
                {
                    this.AddAlertMessage("error", "You cannot unlink this account because you would lose your ability to login.");
                    return(Response.AsRedirect("~/account/#identityProviders"));
                }

                var identity = user.Identities.FirstOrDefault(i => i.ProviderName == provider);

                if (identity != null)
                {
                    repository.Remove(identity);

                    this.AddAlertMessage("success", String.Format("Successfully unlinked {0} account.", provider));
                    return(Response.AsRedirect("~/account/#identityProviders"));
                }

                return(HttpStatusCode.BadRequest);
            };

            Post["/newpassword"] = _ =>
            {
                if (Context.CurrentUser == null)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string password        = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Context.CurrentUser.UserName);

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.SetUserPassword(user, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    this.AddAlertMessage("success", "Successfully added a password.");
                    return(Response.AsRedirect("~/account/#changePassword"));
                }

                return(GetProfileView(authService, user));
            };

            Post["/changepassword"] = _ =>
            {
                if (Context.CurrentUser == null)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string oldPassword     = Request.Form.oldPassword;
                string password        = Request.Form.password;
                string confirmPassword = Request.Form.confirmPassword;

                if (String.IsNullOrEmpty(oldPassword))
                {
                    this.AddValidationError("oldPassword", "Old password is required");
                }

                ValidatePassword(password, confirmPassword);

                ChatUser user = repository.GetUserById(Context.CurrentUser.UserName);

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserPassword(user, oldPassword, password);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    this.AddAlertMessage("success", "Successfully changed your password.");
                    return(Response.AsRedirect("~/account/#changePassword"));
                }

                return(GetProfileView(authService, user));
            };

            Post["/changeusername"] = _ =>
            {
                if (Context.CurrentUser == null)
                {
                    return(HttpStatusCode.Forbidden);
                }

                string username        = Request.Form.username;
                string confirmUsername = Request.Form.confirmUsername;

                ValidateUsername(username, confirmUsername);

                ChatUser user        = repository.GetUserById(Context.CurrentUser.UserName);
                string   oldUsername = user.Name;

                try
                {
                    if (ModelValidationResult.IsValid)
                    {
                        membershipService.ChangeUserName(user, username);
                        repository.CommitChanges();
                    }
                }
                catch (Exception ex)
                {
                    this.AddValidationError("_FORM", ex.Message);
                }

                if (ModelValidationResult.IsValid)
                {
                    notificationService.OnUserNameChanged(user, oldUsername, username);

                    this.AddAlertMessage("success", "Successfully changed your username.");
                    return(Response.AsRedirect("~/account/#changeUsername"));
                }

                return(GetProfileView(authService, user));
            };
        }
Beispiel #24
0
        private void HandleUnallow(ChatUser user, string[] parts)
        {
            if (parts.Length == 1)
            {
                throw new InvalidOperationException("Which user to you want to revoke persmissions from?");
            }

            string targetUserName = parts[1];

            ChatUser targetUser = _repository.VerifyUser(targetUserName);

            if (parts.Length == 2)
            {
                throw new InvalidOperationException("Which room?");
            }

            string   roomName   = parts[2];
            ChatRoom targetRoom = _repository.VerifyRoom(roomName);

            _chatService.UnallowUser(user, targetUser, targetRoom);

            _notificationService.UnallowUser(targetUser, targetRoom);

            _repository.CommitChanges();
        }
Beispiel #25
0
        public NotificationsModule(IJabbrRepository repository,
                                   IChatService chatService,
                                   IChatNotificationService notificationService)
            : base("/notifications")
        {
            Get["/"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(Response.AsRedirect(String.Format("~/account/login?returnUrl={0}", HttpUtility.UrlEncode(Request.Path))));
                }

                var request = this.Bind <NotificationRequestModel>();

                ChatUser user        = repository.GetUserById(Principal.GetUserId());
                int      unreadCount = repository.GetUnreadNotificationsCount(user);
                IPagedList <NotificationViewModel> notifications = GetNotifications(repository, user, all: request.All, page: request.Page, roomName: request.Room);

                var viewModel = new NotificationsViewModel
                {
                    ShowAll       = request.All,
                    UnreadCount   = unreadCount,
                    Notifications = notifications,
                };

                return(View["index", viewModel]);
            };

            Post["/markasread"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                int notificationId = Request.Form.notificationId;

                Notification notification = repository.GetNotificationById(notificationId);

                if (notification == null)
                {
                    return(HttpStatusCode.NotFound);
                }

                ChatUser user = repository.GetUserById(Principal.GetUserId());

                if (notification.UserKey != user.Key)
                {
                    return(HttpStatusCode.Forbidden);
                }

                notification.Read = true;
                repository.CommitChanges();

                UpdateUnreadCountInChat(repository, notificationService, user);

                var response = Response.AsJson(new { success = true });

                return(response);
            };

            Post["/markallasread"] = _ =>
            {
                if (!IsAuthenticated)
                {
                    return(HttpStatusCode.Forbidden);
                }

                ChatUser             user = repository.GetUserById(Principal.GetUserId());
                IList <Notification> unReadNotifications = repository.GetNotificationsByUser(user).Unread().ToList();

                if (!unReadNotifications.Any())
                {
                    return(HttpStatusCode.NotFound);
                }

                foreach (var notification in unReadNotifications)
                {
                    notification.Read = true;
                }

                repository.CommitChanges();

                UpdateUnreadCountInChat(repository, notificationService, user);

                var response = Response.AsJson(new { success = true });

                return(response);
            };
        }