Skip to content

Commit

Permalink
forget pass
Browse files Browse the repository at this point in the history
  • Loading branch information
imnapo committed Dec 26, 2018
1 parent cd8e15b commit 7e7ded9
Show file tree
Hide file tree
Showing 12 changed files with 513 additions and 4 deletions.
109 changes: 109 additions & 0 deletions Controllers/AccountController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using cn_react_dotnetcore.Core.Services;
using cn_react_dotnetcore.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -16,18 +19,22 @@ public class AccountController : Controller
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly IOptions<IdentityOptions> _identityOptions;
private readonly ApplicationDbContext _applicationDbContext;

private readonly IEmailSender _emailSender;
private static bool _databaseChecked;

public AccountController(
UserManager<ApplicationUser> userManager,
IOptions<IdentityOptions> identityOptions,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ApplicationDbContext applicationDbContext
)
{
_userManager = userManager;
_identityOptions = identityOptions;
_signInManager = signInManager;
_emailSender = emailSender;
_applicationDbContext = applicationDbContext;
}

Expand Down Expand Up @@ -81,6 +88,108 @@ public async Task<IActionResult> Register([FromBody] RegisterViewModel model)
}


[AllowAnonymous]
[HttpPost("~/api/auth/forgetPassword")]
public async Task<IActionResult> ForgetPassword(string username)
{

if(username == null)
{
return null;
}

var user = await _userManager.FindByEmailAsync(username);
if(user == null)
{
user = await _userManager.FindByNameAsync(username);
if (user == null)
{
throw new System.ApplicationException($"Unable to load user with ID '{username}'.");

}
}

// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
// Send an email with this link
var code = await _userManager.GeneratePasswordResetTokenAsync(user);

var firstTimeLoginUrl = "http://localhost:5000/resetPassword/username/" + user.Id + "/code/" + code;

// await _emailSender.SendEmailAsync(model.Email, model.EmployeeNo, "Welcome to Intranet",
// "Please complete your registration by clicking this link: <a href=\"" + firstTimeLoginUrl + "\">link</a>"
// , firstTimeLoginUrl);

await _emailSender.SendEmailAsync(user.Email, "Reset Password",
"Please clicking view button to reset your password."
);

return Ok();

}


[HttpPost("~/api/auth/resetPassword")]
[AllowAnonymous]
// [ValidateAntiForgeryToken]
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
{

ApplicationUser user = await _userManager.FindByEmailAsync(model.Email);
if (user == null)
{
user = await _userManager.FindByNameAsync(model.EmployeeNo);

if (user == null)
{
// Don't reveal that the user does not exist
return BadRequest("the user does not exist");
}
}

var code = model.Code.Replace(" ", "+");

var resetResult = await _userManager.ResetPasswordAsync(user, code, model.Password);
if (resetResult.Succeeded)
{

return Ok();
}

return BadRequest(resetResult);
}

[HttpPost("~/api/auth/changePassword")]
[Authorize(AuthenticationSchemes = "Bearer")]
// [ValidateAntiForgeryToken]
public async Task<IActionResult> ChangePassword(ChangePasswordViewModel model)
{
var claimsIdentity = User.Identity as ClaimsIdentity;
string username = claimsIdentity.Name;

ApplicationUser user = await _userManager.FindByNameAsync(username);

if (user == null)
{
// Don't reveal that the user does not exist
return BadRequest("the user does not exist");
}
if(model.NewPassword != model.ConfirmPassword)
{
return BadRequest("the password and confirm password not match.");
}


var resetResult = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);
if (resetResult.Succeeded)
{

return Ok();
}

return BadRequest(resetResult);
}


// The following code creates the database and schema if they don't exist.
// This is a temporary workaround since deploying database through EF migrations is
// not yet supported in this release.
Expand Down
17 changes: 17 additions & 0 deletions Core/Services/FileEmailSender.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.IO;
using System.Threading.Tasks;

namespace cn_react_dotnetcore.Core.Services
{
public class FileEmailSender : IEmailSender
{
public Task SendEmailAsync(string email, string subject, string message)
{
var emailMessage = $"To: {email}\nSubject: {subject}\nMessage: {message}\n\n";

File.AppendAllText("emails.html", emailMessage);

return Task.FromResult(0);
}
}
}
10 changes: 10 additions & 0 deletions Core/Services/IEmailSender.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Threading.Tasks;

namespace cn_react_dotnetcore.Core.Services
{
public interface IEmailSender
{
Task SendEmailAsync(string email, string subject, string message);

}
}
3 changes: 2 additions & 1 deletion Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using MyApp.Core.Models;
using Microsoft.AspNetCore.Identity;
using AspNet.Security.OpenIdConnect.Primitives;
using cn_react_dotnetcore.Core.Services;

namespace MyApp
{
Expand All @@ -28,7 +29,7 @@ public Startup(IConfiguration configuration)
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();

services.AddTransient<IEmailSender, FileEmailSender>();
services.AddDbContext<ApplicationDbContext>(o =>
{
o.UseSqlServer(Configuration.GetConnectionString("Default"));
Expand Down
11 changes: 11 additions & 0 deletions ViewModels/ChangePasswordViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace cn_react_dotnetcore.ViewModels
{
public class ChangePasswordViewModel
{
public string OldPassword { get; set; }

public string NewPassword { get; set; }

public string ConfirmPassword { get; set; }
}
}
33 changes: 33 additions & 0 deletions ViewModels/ResetPasswordViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.ComponentModel.DataAnnotations;

namespace cn_react_dotnetcore.ViewModels
{
public class ResetPasswordViewModel
{
public string FullName { get; set; }

public bool HasError { get; set; }

[Required]
[EmailAddress]
public string Email { get; set; }


[Required]
[StringLength(4)]
[RegularExpression(@"\d{4}")]
public string EmployeeNo { get; set; }

[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; }

[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }

public string Code { get; set; }
}
}
117 changes: 117 additions & 0 deletions src/actions/AuthActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,120 @@ export const userLogout = () => {
}
}

export const forgotPassword = (username) => {
return async (dispatch) => {


var params = `username=${username}`;
try {
let response = await axios.post(`${AUTH_SERVER_URL}/api/auth/forgetPassword`, params, header);

dispatch({ type: FORGOT_PASSWORD_SENT });


if(callback)
callback();
} catch (error) {
console.log(error)
dispatch({ type: LOGIN_USER_FAIL });
}

};
}

export const changePassword = (password, newPassword, confirmPassword, callback) => {
return async (dispatch) => {
var params = `oldPassword=${password}&newPassword=${newPassword}&confirmPassword=${confirmPassword}`;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.headers.post['Authorization'] = `Bearer ${localStorage.getItem('accessToken')}`;
try {
let response = await axios.post(`${AUTH_SERVER_URL}api/auth/changePassword`, params);
dispatch({
type: CHANGE_PASSWORD_SUCCEESS,
});

if(callback)
callback({
succeed : true,
error: ''
});
} catch (error) {
if(callback)
callback({
succeed : false,
error: 'something went wrong!'
});
}
};
}

export const resetPassword = (email, code, password, confirmPassword, callback) => {
return async (dispatch) => {
var params = `email=${email}&code=${code}&password=${password}&confirmPassword=${confirmPassword}`;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
try {
let response = await axios.post(`${AUTH_SERVER_URL}api/auth/resetPassword`, params);
dispatch({
type: RESET_PASSWORD_SUCCEESS,
});

if(callback)
callback({
succeed : true,
error: ''
});
}
catch (error) {
if(callback)
callback({
succeed : false,
error: 'something went wrong!'
});
}
};
}

export const getResetPasswordInfo = (username, code, callback) => {
return async (dispatch) => {
var params = `userId=${username}&code=${code}`;
try {
let response = await axios.get(`${AUTH_SERVER_URL}api/auth/resetPassword?${params}`);
dispatch({
type:GET_FIRST_LOGIN_INFO,
payload:response.data
});
} catch (error) {
if(callback)
callback();
}

};
}

export const getAccessTokenAsync = async () => {


let token = await _getItem('accessToken');
let expiration = await _getItem('expiresAt');
if(token && expiration) {
if(isExpired(expiration) == false) {

return token;
}
else {
let refToken = await _getItem('refreshToken');
const response = await refreshTokenApiAsync(refToken);
await _saveItem('accessToken', response.data.access_token);
const now = new Date();
let expirationDate = new Date(now.getTime() + response.data.expires_in * 1000).getTime().toString();
await _saveItem('expiresAt', expirationDate);
await _saveItem('idToken', response.data.id_token);

return response.data.access_token;

}
}
else {

}
}
Loading

0 comments on commit 7e7ded9

Please sign in to comment.