Beispiel #1
0
        public async Task <ActionResult> ConfirmMemberRequest(string accountName, string confirmationToken)
        {
            var account = GetAccount(accountName);

            if (account == null)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.NotFound));
            }

            try
            {
                var member = await UserService.AddMemberAsync(account, GetCurrentUser().Username, confirmationToken);

                var emailMessage = new OrganizationMemberUpdatedMessage(MessageServiceConfiguration, account, member);
                await MessageService.SendMessageAsync(emailMessage);

                TempData["Message"] = String.Format(CultureInfo.CurrentCulture,
                                                    Strings.AddMember_Success, account.Username);

                return(Redirect(Url.ManageMyOrganization(account.Username)));
            }
            catch (EntityException e)
            {
                var failureReason = e.AsUserSafeException().GetUserSafeMessage();
                return(HandleOrganizationMembershipRequestView(new HandleOrganizationMembershipRequestModel(true, account, failureReason)));
            }
        }
        public virtual async Task <ActionResult> ConfirmTransformToOrganization(string accountNameToTransform, string token)
        {
            var adminUser = GetCurrentUser();

            string errorReason;
            var    accountToTransform = UserService.FindByUsername(accountNameToTransform);

            if (accountToTransform == null)
            {
                errorReason = String.Format(CultureInfo.CurrentCulture,
                                            Strings.TransformAccount_OrganizationAccountDoesNotExist, accountNameToTransform);
                return(TransformToOrganizationFailed(errorReason));
            }

            if (!UserService.CanTransformUserToOrganization(accountToTransform, out errorReason))
            {
                return(TransformToOrganizationFailed(errorReason));
            }

            if (!await UserService.TransformUserToOrganization(accountToTransform, adminUser, token))
            {
                errorReason = Strings.TransformAccount_Failed;
                return(TransformToOrganizationFailed(errorReason));
            }

            var emailMessage = new OrganizationTransformAcceptedMessage(_config, accountToTransform, adminUser);
            await MessageService.SendMessageAsync(emailMessage);

            TelemetryService.TrackOrganizationTransformCompleted(accountToTransform);

            TempData["Message"] = string.Format(CultureInfo.CurrentCulture,
                                                Strings.TransformAccount_Success, accountNameToTransform);

            return(Redirect(Url.ManageMyOrganization(accountNameToTransform)));
        }
        public virtual async Task <ActionResult> RejectTransformToOrganization(string accountNameToTransform, string token)
        {
            var adminUser = GetCurrentUser();

            string message;
            var    accountToTransform = UserService.FindByUsername(accountNameToTransform);

            if (accountToTransform == null)
            {
                message = String.Format(CultureInfo.CurrentCulture,
                                        Strings.TransformAccount_OrganizationAccountDoesNotExist, accountNameToTransform);
            }
            else
            {
                if (await UserService.RejectTransformUserToOrganizationRequest(accountToTransform, adminUser, token))
                {
                    var emailMessage = new OrganizationTransformRejectedMessage(_config, accountToTransform, adminUser, isCanceledByAdmin: true);
                    await MessageService.SendMessageAsync(emailMessage);

                    TelemetryService.TrackOrganizationTransformDeclined(accountToTransform);

                    message = string.Format(CultureInfo.CurrentCulture,
                                            Strings.TransformAccount_Rejected, accountNameToTransform);
                }
                else
                {
                    message = Strings.TransformAccount_FailedMissingRequestToCancel;
                }
            }

            TempData["Message"] = message;

            return(RedirectToAction(actionName: "Home", controllerName: "Pages"));
        }
Beispiel #4
0
        public async Task <ActionResult> RejectMemberRequest(string accountName, string confirmationToken)
        {
            var account = GetAccount(accountName);

            if (account == null)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.NotFound));
            }

            try
            {
                var member = GetCurrentUser();
                await UserService.RejectMembershipRequestAsync(account, member.Username, confirmationToken);

                var emailMessage = new OrganizationMembershipRequestDeclinedMessage(MessageServiceConfiguration, account, member);
                await MessageService.SendMessageAsync(emailMessage);

                return(HandleOrganizationMembershipRequestView(new HandleOrganizationMembershipRequestModel(false, account)));
            }
            catch (EntityException e)
            {
                var failureReason = e.AsUserSafeException().GetUserSafeMessage();
                return(HandleOrganizationMembershipRequestView(new HandleOrganizationMembershipRequestModel(false, account, failureReason)));
            }
        }
Beispiel #5
0
        public async Task <JsonResult> UpdateMember(string accountName, string memberName, bool isAdmin)
        {
            var account = GetAccount(accountName);

            if (account == null ||
                ActionsRequiringPermissions.ManageMembership.CheckPermissions(GetCurrentUser(), account)
                != PermissionsCheckResult.Allowed)
            {
                return(Json(HttpStatusCode.Forbidden, Strings.Unauthorized));
            }

            if (!account.Confirmed)
            {
                return(Json(HttpStatusCode.BadRequest, Strings.Member_OrganizationUnconfirmed));
            }

            try
            {
                var membership = await UserService.UpdateMemberAsync(account, memberName, isAdmin);

                var emailMessage = new OrganizationMemberUpdatedMessage(MessageServiceConfiguration, account, membership);
                await MessageService.SendMessageAsync(emailMessage);

                return(Json(new OrganizationMemberViewModel(membership)));
            }
            catch (EntityException e)
            {
                return(Json(HttpStatusCode.BadRequest, e.Message));
            }
        }
Beispiel #6
0
        public async Task <JsonResult> DeleteMember(string accountName, string memberName)
        {
            var account = GetAccount(accountName);

            var currentUser = GetCurrentUser();

            if (account == null ||
                (currentUser.Username != memberName &&
                 ActionsRequiringPermissions.ManageMembership.CheckPermissions(currentUser, account)
                 != PermissionsCheckResult.Allowed))
            {
                return(Json(HttpStatusCode.Forbidden, Strings.Unauthorized));
            }

            if (!account.Confirmed)
            {
                return(Json(HttpStatusCode.BadRequest, Strings.Member_OrganizationUnconfirmed));
            }

            try
            {
                var removedMember = await UserService.DeleteMemberAsync(account, memberName);

                var emailMessage = new OrganizationMemberRemovedMessage(MessageServiceConfiguration, account, removedMember);

                await MessageService.SendMessageAsync(emailMessage);

                return(Json(Strings.DeleteMember_Success));
            }
            catch (EntityException e)
            {
                return(Json(HttpStatusCode.BadRequest, e.Message));
            }
        }
        protected override Task SendNewAccountEmailAsync(User account)
        {
            var message = new NewAccountMessage(
                MessageServiceConfiguration,
                account,
                Url.ConfirmEmail(account.Username, account.EmailConfirmationToken, relativeUrl: false));

            return(MessageService.SendMessageAsync(message));
        }
Beispiel #8
0
        protected override Task SendEmailChangedConfirmationNoticeAsync(User account)
        {
            var message = new EmailChangeConfirmationMessage(
                MessageServiceConfiguration,
                account,
                Url.ConfirmOrganizationEmail(account.Username, account.EmailConfirmationToken, relativeUrl: false));

            return(MessageService.SendMessageAsync(message));
        }
        public virtual async Task <JsonResult> GenerateApiKey(string description, string owner, string[] scopes = null, string[] subjects = null, int?expirationInDays = null)
        {
            if (string.IsNullOrWhiteSpace(description))
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return(Json(Strings.ApiKeyDescriptionRequired));
            }
            if (string.IsNullOrWhiteSpace(owner))
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return(Json(Strings.ApiKeyOwnerRequired));
            }

            // Get the owner scope
            User scopeOwner = UserService.FindByUsername(owner);

            if (scopeOwner == null)
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return(Json(Strings.UserNotFound));
            }

            var resolvedScopes = BuildScopes(scopeOwner, scopes, subjects);

            if (!VerifyScopes(resolvedScopes))
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return(Json(Strings.ApiKeyScopesNotAllowed));
            }

            // Set expiration
            var expiration = TimeSpan.Zero;

            if (_config.ExpirationInDaysForApiKeyV1 > 0)
            {
                expiration = TimeSpan.FromDays(_config.ExpirationInDaysForApiKeyV1);

                if (expirationInDays.HasValue && expirationInDays.Value > 0)
                {
                    expiration = TimeSpan.FromDays(Math.Min(expirationInDays.Value, _config.ExpirationInDaysForApiKeyV1));
                }
            }

            var newCredentialViewModel = await GenerateApiKeyInternal(description, resolvedScopes, expiration);

            var emailMessage = new CredentialAddedMessage(
                _config,
                GetCurrentUser(),
                newCredentialViewModel.GetCredentialTypeInfo());
            await MessageService.SendMessageAsync(emailMessage);

            return(Json(new ApiKeyViewModel(newCredentialViewModel)));
        }
Beispiel #10
0
        public virtual async Task <ActionResult> Confirm(string accountName, string token)
        {
            // We don't want Login to go to this page as a return URL
            // By having this value present in the dictionary BUT null, we don't put "returnUrl" on the Login link at all
            ViewData[GalleryConstants.ReturnUrlViewDataKey] = null;

            var account = GetAccount(accountName);

            if (account == null ||
                ActionsRequiringPermissions.ManageAccount.CheckPermissions(GetCurrentUser(), account)
                != PermissionsCheckResult.Allowed)
            {
                return(View(new ConfirmationViewModel(accountName)
                {
                    WrongUsername = true,
                    SuccessfulConfirmation = false
                }));
            }

            string existingEmail = account.EmailAddress;
            var    model         = new ConfirmationViewModel(account);

            if (!model.AlreadyConfirmed)
            {
                try
                {
                    model.SuccessfulConfirmation = await UserService.ConfirmEmailAddress(account, token);
                }
                catch (EntityException)
                {
                    model.SuccessfulConfirmation = false;
                    model.DuplicateEmailAddress  = true;
                }

                // SuccessfulConfirmation is required so that the confirm Action isn't a way to spam people.
                // Change notice not required for new accounts.
                if (model.SuccessfulConfirmation && !model.ConfirmingNewAccount)
                {
                    var message = new EmailChangeNoticeToPreviousEmailAddressMessage(MessageServiceConfiguration, account, existingEmail);
                    await MessageService.SendMessageAsync(message);

                    string returnUrl = HttpContext.GetConfirmationReturnUrl();
                    if (!String.IsNullOrEmpty(returnUrl))
                    {
                        TempData["Message"] = Messages.EmailConfirmed;
                        return(SafeRedirect(returnUrl));
                    }
                }
            }

            return(View(model));
        }
Beispiel #11
0
        public async Task <JsonResult> AddMember(string accountName, string memberName, bool isAdmin)
        {
            var account = GetAccount(accountName);

            if (account == null ||
                ActionsRequiringPermissions.ManageMembership.CheckPermissions(GetCurrentUser(), account)
                != PermissionsCheckResult.Allowed)
            {
                return(Json(HttpStatusCode.Forbidden, Strings.Unauthorized));
            }

            if (!account.Confirmed)
            {
                return(Json(HttpStatusCode.BadRequest, Strings.Member_OrganizationUnconfirmed));
            }

            try
            {
                var request = await UserService.AddMembershipRequestAsync(account, memberName, isAdmin);

                var currentUser = GetCurrentUser();

                var organizationMembershipRequestMessage = new OrganizationMembershipRequestMessage(
                    MessageServiceConfiguration,
                    account,
                    request.NewMember,
                    currentUser,
                    request.IsAdmin,
                    profileUrl: Url.User(account, relativeUrl: false),
                    confirmationUrl: Url.AcceptOrganizationMembershipRequest(request, relativeUrl: false),
                    rejectionUrl: Url.RejectOrganizationMembershipRequest(request, relativeUrl: false));
                await MessageService.SendMessageAsync(organizationMembershipRequestMessage);

                var organizationMembershipRequestInitiatedMessage = new OrganizationMembershipRequestInitiatedMessage(
                    MessageServiceConfiguration,
                    account,
                    currentUser,
                    request.NewMember,
                    request.IsAdmin,
                    cancellationUrl: Url.CancelOrganizationMembershipRequest(memberName, relativeUrl: false));
                await MessageService.SendMessageAsync(organizationMembershipRequestInitiatedMessage);

                return(Json(new OrganizationMemberViewModel(request)));
            }
            catch (EntityException e)
            {
                return(Json(HttpStatusCode.BadRequest, e.Message));
            }
        }
Beispiel #12
0
        public virtual async Task <ActionResult> ResetPassword(string username, string token, PasswordResetViewModel model, bool forgot)
        {
            // We don't want Login to have us as a return URL
            // By having this value present in the dictionary BUT null, we don't put "returnUrl" on the Login link at all
            ViewData[GalleryConstants.ReturnUrlViewDataKey] = null;

            if (!ModelState.IsValid)
            {
                return(ResetPassword(forgot));
            }

            ViewBag.ForgotPassword = forgot;

            Credential credential = null;

            try
            {
                credential = await AuthenticationService.ResetPasswordWithToken(username, token, model.NewPassword);
            }
            catch (InvalidOperationException ex)
            {
                ModelState.AddModelError(string.Empty, ex.Message);
                return(View(model));
            }

            ViewBag.ResetTokenValid = credential != null;

            if (!ViewBag.ResetTokenValid)
            {
                ModelState.AddModelError(string.Empty, Strings.InvalidOrExpiredPasswordResetToken);
                return(View(model));
            }

            if (credential != null && !forgot)
            {
                // Setting a password, so notify the user
                var emailMessage = new CredentialAddedMessage(
                    _config,
                    credential.User,
                    AuthenticationService.DescribeCredential(credential).GetCredentialTypeInfo());
                await MessageService.SendMessageAsync(emailMessage);
            }

            return(RedirectToAction("PasswordChanged"));
        }
Beispiel #13
0
        private async Task <ActionResult> SendPasswordResetEmailAsync(User user, bool forgotPassword)
        {
            var resetPasswordUrl = Url.ResetEmailOrPassword(
                user.Username,
                user.PasswordResetToken,
                forgotPassword,
                relativeUrl: false);

            var message = new PasswordResetInstructionsMessage(
                MessageServiceConfiguration,
                user,
                resetPasswordUrl,
                forgotPassword);

            await MessageService.SendMessageAsync(message);

            return(RedirectToAction(actionName: "PasswordSent", controllerName: "Users"));
        }
        public override async Task <ActionResult> RequestAccountDeletion(string accountName = null)
        {
            var user = GetAccount(accountName);

            if (user == null || user.IsDeleted)
            {
                return(HttpNotFound());
            }
            TelemetryService.TrackRequestForAccountDeletion(user);

            if (!user.Confirmed)
            {
                // Unconfirmed users can be deleted immediately without creating a support request.
                DeleteUserAccountStatus accountDeleteStatus = await _deleteAccountService.DeleteAccountAsync(userToBeDeleted : user,
                                                                                                             userToExecuteTheDelete : user,
                                                                                                             orphanPackagePolicy : AccountDeletionOrphanPackagePolicy.UnlistOrphans,
                                                                                                             commitAsTransaction : true);

                if (!accountDeleteStatus.Success)
                {
                    TempData["RequestFailedMessage"] = Strings.AccountSelfDelete_Fail;
                    return(RedirectToAction("DeleteRequest"));
                }
                OwinContext.Authentication.SignOut();
                return(SafeRedirect(Url.Home(false)));
            }

            var isSupportRequestCreated = await _supportRequestService.TryAddDeleteSupportRequestAsync(user);

            if (isSupportRequestCreated)
            {
                var emailMessage = new AccountDeleteNoticeMessage(MessageServiceConfiguration, user);
                await MessageService.SendMessageAsync(emailMessage);
            }
            else
            {
                TempData["RequestFailedMessage"] = Strings.AccountDelete_CreateSupportRequestFails;
            }

            return(RedirectToAction(nameof(DeleteRequest)));
        }
Beispiel #15
0
        private async Task <JsonResult> RemoveApiKeyCredential(User user, Credential cred)
        {
            if (cred == null)
            {
                Response.StatusCode = (int)HttpStatusCode.NotFound;
                return(Json(Strings.CredentialNotFound));
            }

            var credentialTypeInfo = AuthenticationService.DescribeCredential(cred).GetCredentialTypeInfo();

            await AuthenticationService.RemoveCredential(user, cred);

            // Notify the user of the change
            var emailMessage = new CredentialRemovedMessage(
                _config,
                user,
                credentialTypeInfo);
            await MessageService.SendMessageAsync(emailMessage);

            return(Json(Strings.CredentialRemoved));
        }
Beispiel #16
0
        public virtual async Task <ActionResult> CancelTransformToOrganization(string token)
        {
            var accountToTransform = GetCurrentUser();
            var adminUser          = accountToTransform.OrganizationMigrationRequest?.AdminUser;

            if (await UserService.CancelTransformUserToOrganizationRequest(accountToTransform, token))
            {
                var emailMessage = new OrganizationTransformRejectedMessage(_config, accountToTransform, adminUser, isCanceledByAdmin: false);
                await MessageService.SendMessageAsync(emailMessage);

                TelemetryService.TrackOrganizationTransformCancelled(accountToTransform);

                TempData["Message"] = String.Format(CultureInfo.CurrentCulture,
                                                    Strings.TransformAccount_Cancelled);
            }
            else
            {
                TempData["ErrorMessage"] = Strings.TransformAccount_FailedMissingRequestToCancel;
            }

            return(RedirectToAction(actionName: "Home", controllerName: "Pages"));
        }
Beispiel #17
0
        public override async Task <ActionResult> RequestAccountDeletion(string accountName = null)
        {
            var user = GetAccount(accountName);

            if (user == null || user.IsDeleted)
            {
                return(HttpNotFound());
            }
            TelemetryService.TrackRequestForAccountDeletion(user);

            if (_config.SelfServiceAccountDeleteEnabled && _featureFlagService.IsSelfServiceAccountDeleteEnabled())
            {
                return(await DeleteAndCheckSuccess(user));
            }
            else
            {
                if (!user.Confirmed)
                {
                    // Unconfirmed users can be deleted immediately without creating a support request.
                    return(await DeleteAndCheckSuccess(user));
                }

                var isSupportRequestCreated = await _supportRequestService.TryAddDeleteSupportRequestAsync(user);

                if (isSupportRequestCreated)
                {
                    var emailMessage = new AccountDeleteNoticeMessage(MessageServiceConfiguration, user);
                    await MessageService.SendMessageAsync(emailMessage);

                    return(RedirectToAction(nameof(DeleteRequest)));
                }
                else
                {
                    TempData["RequestFailedMessage"] = Strings.AccountDelete_CreateSupportRequestFails;

                    return(RedirectToAction(nameof(DeleteRequest)));
                }
            }
        }
Beispiel #18
0
        private async Task <ActionResult> RemoveCredentialInternal(User user, Credential cred, string message)
        {
            if (cred == null)
            {
                TempData["Message"] = Strings.CredentialNotFound;

                return(RedirectToAction("Account"));
            }

            // Count credentials and make sure the user can always login
            if (!cred.IsApiKey() && CountLoginCredentials(user) <= 1)
            {
                TempData["Message"] = Strings.CannotRemoveOnlyLoginCredential;
            }
            else
            {
                await AuthenticationService.RemoveCredential(user, cred);

                if (cred.IsPassword())
                {
                    // Clear the password login claim, to remove warnings.
                    OwinContext.RemoveClaim(NuGetClaims.PasswordLogin);
                }

                // Notify the user of the change
                var emailMessage = new CredentialRemovedMessage(
                    _config,
                    user,
                    AuthenticationService.DescribeCredential(cred).GetCredentialTypeInfo());
                await MessageService.SendMessageAsync(emailMessage);

                TempData["Message"] = message;
            }

            return(RedirectToAction("Account"));
        }
Beispiel #19
0
        public virtual async Task <ActionResult> TransformToOrganization(TransformAccountViewModel transformViewModel)
        {
            var accountToTransform = GetCurrentUser();

            var adminUsername = transformViewModel.AdminUsername;

            if (Regex.IsMatch(adminUsername, GalleryConstants.EmailValidationRegex, RegexOptions.None, GalleryConstants.EmailValidationRegexTimeout))
            {
                ModelState.AddModelError(string.Empty, Strings.TransformAccount_AdminNameIsEmail);
                return(View(transformViewModel));
            }

            var adminUser = UserService.FindByUsername(adminUsername);

            if (adminUser == null)
            {
                ModelState.AddModelError(string.Empty, string.Format(CultureInfo.CurrentCulture,
                                                                     Strings.TransformAccount_AdminAccountDoesNotExist, adminUsername));
                return(View(transformViewModel));
            }

            if (!UserService.CanTransformUserToOrganization(accountToTransform, adminUser, out var errorReason))
            {
                ModelState.AddModelError(string.Empty, errorReason);
                return(View(transformViewModel));
            }

            // Get the user from the previous organization migration request (if there was one) so we can notify them that their request has been cancelled.
            var existingTransformRequestUser = accountToTransform.OrganizationMigrationRequest?.AdminUser;

            await UserService.RequestTransformToOrganizationAccount(accountToTransform, adminUser);

            if (existingTransformRequestUser != null)
            {
                var emailMessage = new OrganizationTransformRejectedMessage(_config, accountToTransform, existingTransformRequestUser, isCanceledByAdmin: false);
                await MessageService.SendMessageAsync(emailMessage);
            }

            var organizationTransformRequestMessage = new OrganizationTransformRequestMessage(
                _config,
                accountToTransform,
                adminUser,
                profileUrl: Url.User(accountToTransform, relativeUrl: false),
                confirmationUrl: Url.ConfirmTransformAccount(accountToTransform, relativeUrl: false),
                rejectionUrl: Url.RejectTransformAccount(accountToTransform, relativeUrl: false));
            await MessageService.SendMessageAsync(organizationTransformRequestMessage);

            var organizationTransformInitiatedMessage = new OrganizationTransformInitiatedMessage(
                _config,
                accountToTransform,
                adminUser,
                cancellationUrl: Url.CancelTransformAccount(accountToTransform, relativeUrl: false));
            await MessageService.SendMessageAsync(organizationTransformInitiatedMessage);

            TelemetryService.TrackOrganizationTransformInitiated(accountToTransform);

            // sign out pending organization and prompt for admin sign in
            OwinContext.Authentication.SignOut();

            TempData[GalleryConstants.ReturnUrlMessageViewDataKey] = String.Format(CultureInfo.CurrentCulture,
                                                                                   Strings.TransformAccount_SignInToConfirm, adminUser.Username, accountToTransform.Username);

            var returnUrl = Url.ConfirmTransformAccount(accountToTransform);

            return(Redirect(Url.LogOn(returnUrl)));
        }