/RealState-Site/Site/Areas/Customer/Controllers/AccountController.cs
C# | 409 lines | 323 code | 38 blank | 48 comment | 40 complexity | 13f433ac35dfa948f0632c9dc57b2844 MD5 | raw file
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Security.Claims;
5using System.Threading.Tasks;
6using System.Web;
7using System.Web.Mvc;
8using Microsoft.AspNet.Identity;
9using Microsoft.AspNet.Identity.EntityFramework;
10using Microsoft.Owin.Security;
11using Site.Areas.Customer.Models;
12
13
14namespace Site.Areas.Customer.Controllers
15{
16 //[Authorize]
17 public class AccountController : BaseController
18 {
19 //public AccountController()
20 // : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
21 //{
22 //}
23
24 //public AccountController(UserManager<ApplicationUser> userManager)
25 //{
26 // UserManager = userManager;
27 //}
28
29 //public UserManager<ApplicationUser> UserManager { get; private set; }
30
31 //
32 // GET: /Account/Login
33 [AllowAnonymous]
34 public ActionResult Login(string returnUrl)
35 {
36 ViewBag.ReturnUrl = returnUrl;
37 return View();
38 }
39
40 //
41 // POST: /Account/Login
42 [HttpPost]
43 [AllowAnonymous]
44 [ValidateAntiForgeryToken]
45 public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
46 {
47 if (ModelState.IsValid)
48 {
49 var user = await UserManager.FindAsync(model.UserName, model.Password);
50 if (user != null)
51 {
52 await SignInAsync(user, model.RememberMe);
53 return RedirectToLocal(returnUrl);
54 }
55 else
56 {
57 ModelState.AddModelError("", "Invalid username or password.");
58 }
59 }
60
61 // If we got this far, something failed, redisplay form
62 return View(model);
63 }
64
65 //
66 // GET: /Account/Register
67 [AllowAnonymous]
68 public ActionResult Register()
69 {
70 return View();
71 }
72
73 //
74 // POST: /Account/Register
75 [HttpPost]
76 [AllowAnonymous]
77 [ValidateAntiForgeryToken]
78 public async Task<ActionResult> Register(RegisterViewModel model)
79 {
80 if (ModelState.IsValid)
81 {
82 var user = new ApplicationUser() { UserName = model.UserName };
83 var result = await UserManager.CreateAsync(user, model.Password);
84 if (result.Succeeded)
85 {
86 await SignInAsync(user, isPersistent: false);
87 return RedirectToAction("Index", "Home");
88 }
89 else
90 {
91 AddErrors(result);
92 }
93 }
94
95 // If we got this far, something failed, redisplay form
96 return View(model);
97 }
98
99 //
100 // POST: /Account/Disassociate
101 [HttpPost]
102 [ValidateAntiForgeryToken]
103 public async Task<ActionResult> Disassociate(string loginProvider, string providerKey)
104 {
105 ManageMessageId? message = null;
106 IdentityResult result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
107 if (result.Succeeded)
108 {
109 message = ManageMessageId.RemoveLoginSuccess;
110 }
111 else
112 {
113 message = ManageMessageId.Error;
114 }
115 return RedirectToAction("Manage", new { Message = message });
116 }
117
118 //
119 // GET: /Account/Manage
120 public ActionResult Manage(ManageMessageId? message)
121 {
122 ViewBag.StatusMessage =
123 message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
124 : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
125 : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
126 : message == ManageMessageId.Error ? "An error has occurred."
127 : "";
128 ViewBag.HasLocalPassword = HasPassword();
129 ViewBag.ReturnUrl = Url.Action("Manage");
130 return View();
131 }
132
133 //
134 // POST: /Account/Manage
135 [HttpPost]
136 [ValidateAntiForgeryToken]
137 public async Task<ActionResult> Manage(ManageUserViewModel model)
138 {
139 bool hasPassword = HasPassword();
140 ViewBag.HasLocalPassword = hasPassword;
141 ViewBag.ReturnUrl = Url.Action("Manage");
142 if (hasPassword)
143 {
144 if (ModelState.IsValid)
145 {
146 IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
147 if (result.Succeeded)
148 {
149 return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
150 }
151 else
152 {
153 AddErrors(result);
154 }
155 }
156 }
157 else
158 {
159 // User does not have a password so remove any validation errors caused by a missing OldPassword field
160 ModelState state = ModelState["OldPassword"];
161 if (state != null)
162 {
163 state.Errors.Clear();
164 }
165
166 if (ModelState.IsValid)
167 {
168 IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
169 if (result.Succeeded)
170 {
171 return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
172 }
173 else
174 {
175 AddErrors(result);
176 }
177 }
178 }
179
180 // If we got this far, something failed, redisplay form
181 return View(model);
182 }
183
184 //
185 // POST: /Account/ExternalLogin
186 [HttpPost]
187 [AllowAnonymous]
188 [ValidateAntiForgeryToken]
189 public ActionResult ExternalLogin(string provider, string returnUrl)
190 {
191 // Request a redirect to the external login provider
192 return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
193 }
194
195 //
196 // GET: /Account/ExternalLoginCallback
197 [AllowAnonymous]
198 public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
199 {
200 var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
201 if (loginInfo == null)
202 {
203 return RedirectToAction("Login");
204 }
205
206 // Sign in the user with this external login provider if the user already has a login
207 var user = await UserManager.FindAsync(loginInfo.Login);
208 if (user != null)
209 {
210 await SignInAsync(user, isPersistent: false);
211 return RedirectToLocal(returnUrl);
212 }
213 else
214 {
215 // If the user does not have an account, then prompt the user to create an account
216 ViewBag.ReturnUrl = returnUrl;
217 ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
218 return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName });
219 }
220 }
221
222 //
223 // POST: /Account/LinkLogin
224 [HttpPost]
225 [ValidateAntiForgeryToken]
226 public ActionResult LinkLogin(string provider)
227 {
228 // Request a redirect to the external login provider to link a login for the current user
229 return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId());
230 }
231
232 //
233 // GET: /Account/LinkLoginCallback
234 public async Task<ActionResult> LinkLoginCallback()
235 {
236 var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
237 if (loginInfo == null)
238 {
239 return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
240 }
241 var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
242 if (result.Succeeded)
243 {
244 return RedirectToAction("Manage");
245 }
246 return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
247 }
248
249 //
250 // POST: /Account/ExternalLoginConfirmation
251 [HttpPost]
252 [AllowAnonymous]
253 [ValidateAntiForgeryToken]
254 public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
255 {
256 if (User.Identity.IsAuthenticated)
257 {
258 return RedirectToAction("Manage");
259 }
260
261 if (ModelState.IsValid)
262 {
263 // Get the information about the user from the external login provider
264 var info = await AuthenticationManager.GetExternalLoginInfoAsync();
265 if (info == null)
266 {
267 return View("ExternalLoginFailure");
268 }
269 var user = new ApplicationUser() { UserName = model.UserName };
270 var result = await UserManager.CreateAsync(user);
271 if (result.Succeeded)
272 {
273 result = await UserManager.AddLoginAsync(user.Id, info.Login);
274 if (result.Succeeded)
275 {
276 await SignInAsync(user, isPersistent: false);
277 return RedirectToLocal(returnUrl);
278 }
279 }
280 AddErrors(result);
281 }
282
283 ViewBag.ReturnUrl = returnUrl;
284 return View(model);
285 }
286
287 //
288 // POST: /Account/LogOff
289 [HttpPost]
290 [ValidateAntiForgeryToken]
291 public ActionResult LogOff()
292 {
293 AuthenticationManager.SignOut();
294 return RedirectToAction("Index", "Home");
295 }
296
297 //
298 // GET: /Account/ExternalLoginFailure
299 [AllowAnonymous]
300 public ActionResult ExternalLoginFailure()
301 {
302 return View();
303 }
304
305 [ChildActionOnly]
306 public ActionResult RemoveAccountList()
307 {
308 var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId());
309 ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
310 return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
311 }
312
313 protected override void Dispose(bool disposing)
314 {
315 if (disposing && UserManager != null)
316 {
317 UserManager.Dispose();
318 UserManager = null;
319 }
320 base.Dispose(disposing);
321 }
322
323 #region Helpers
324 // Used for XSRF protection when adding external logins
325 private const string XsrfKey = "XsrfId";
326
327 private IAuthenticationManager AuthenticationManager
328 {
329 get
330 {
331 return HttpContext.GetOwinContext().Authentication;
332 }
333 }
334
335 private async Task SignInAsync(ApplicationUser user, bool isPersistent)
336 {
337 AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
338 var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
339 AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
340 }
341
342 private void AddErrors(IdentityResult result)
343 {
344 foreach (var error in result.Errors)
345 {
346 ModelState.AddModelError("", error);
347 }
348 }
349
350 private bool HasPassword()
351 {
352 var user = UserManager.FindById(User.Identity.GetUserId());
353 if (user != null)
354 {
355 return user.PasswordHash != null;
356 }
357 return false;
358 }
359
360 public enum ManageMessageId
361 {
362 ChangePasswordSuccess,
363 SetPasswordSuccess,
364 RemoveLoginSuccess,
365 Error
366 }
367
368 private ActionResult RedirectToLocal(string returnUrl)
369 {
370 if (Url.IsLocalUrl(returnUrl))
371 {
372 return Redirect(returnUrl);
373 }
374 else
375 {
376 return RedirectToAction("Index", "Home");
377 }
378 }
379
380 private class ChallengeResult : HttpUnauthorizedResult
381 {
382 public ChallengeResult(string provider, string redirectUri) : this(provider, redirectUri, null)
383 {
384 }
385
386 public ChallengeResult(string provider, string redirectUri, string userId)
387 {
388 LoginProvider = provider;
389 RedirectUri = redirectUri;
390 UserId = userId;
391 }
392
393 public string LoginProvider { get; set; }
394 public string RedirectUri { get; set; }
395 public string UserId { get; set; }
396
397 public override void ExecuteResult(ControllerContext context)
398 {
399 var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
400 if (UserId != null)
401 {
402 properties.Dictionary[XsrfKey] = UserId;
403 }
404 context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
405 }
406 }
407 #endregion
408 }
409}