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")); }
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))); } }
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)); } }
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)); }
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))); }
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)); }
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)); } }
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")); }
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))); }
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)); }
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")); }
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))); } } }
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")); }
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))); }