The next generation of the Teknik Services. Written in ASP.NET. https://www.teknik.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ErrorController.cs 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. using IdentityServer4.Services;
  2. using Microsoft.AspNetCore.Authorization;
  3. using Microsoft.AspNetCore.Diagnostics;
  4. using Microsoft.AspNetCore.Http;
  5. using Microsoft.AspNetCore.Http.Extensions;
  6. using Microsoft.AspNetCore.Mvc;
  7. using Microsoft.Extensions.Logging;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Net.Mail;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using Teknik.Configuration;
  15. using Teknik.IdentityServer.ViewModels;
  16. using Teknik.Logging;
  17. using Teknik.Utilities;
  18. namespace Teknik.IdentityServer.Controllers
  19. {
  20. public class ErrorController : DefaultController
  21. {
  22. private readonly IIdentityServerInteractionService _interaction;
  23. public ErrorController(ILogger<Logger> logger, Config config, IIdentityServerInteractionService interaction) : base(logger, config)
  24. {
  25. _interaction = interaction;
  26. }
  27. public IActionResult HttpError(int statusCode)
  28. {
  29. switch (statusCode)
  30. {
  31. case 401:
  32. return Http401();
  33. case 403:
  34. return Http403();
  35. case 404:
  36. return Http404();
  37. default:
  38. return HttpGeneral(statusCode);
  39. }
  40. }
  41. public IActionResult HttpGeneral(int statusCode)
  42. {
  43. ViewBag.Title = statusCode;
  44. LogError(LogLevel.Error, "HTTP Error Code: " + statusCode);
  45. ErrorViewModel model = new ErrorViewModel();
  46. model.StatusCode = statusCode;
  47. return GenerateActionResult(CreateErrorObj("Http", statusCode, "Invalid HTTP Response"), View("~/Views/Error/HttpGeneral.cshtml", model));
  48. }
  49. [AllowAnonymous]
  50. public IActionResult Http401()
  51. {
  52. Response.StatusCode = StatusCodes.Status401Unauthorized;
  53. ViewBag.Title = "401";
  54. ViewBag.Description = "Unauthorized";
  55. LogError(LogLevel.Error, "Unauthorized");
  56. ErrorViewModel model = new ErrorViewModel();
  57. model.StatusCode = StatusCodes.Status401Unauthorized;
  58. return GenerateActionResult(CreateErrorObj("Http", StatusCodes.Status401Unauthorized, "Unauthorized"), View("~/Views/Error/Http401.cshtml", model));
  59. }
  60. [AllowAnonymous]
  61. public IActionResult Http403()
  62. {
  63. Response.StatusCode = StatusCodes.Status403Forbidden;
  64. ViewBag.Title = "403";
  65. ViewBag.Description = "Access Denied";
  66. LogError(LogLevel.Error, "Access Denied");
  67. ErrorViewModel model = new ErrorViewModel();
  68. model.StatusCode = StatusCodes.Status403Forbidden;
  69. return GenerateActionResult(CreateErrorObj("Http", StatusCodes.Status403Forbidden, "Access Denied"), View("~/Views/Error/Http403.cshtml", model));
  70. }
  71. [AllowAnonymous]
  72. public IActionResult Http404()
  73. {
  74. Response.StatusCode = StatusCodes.Status404NotFound;
  75. ViewBag.Title = "404";
  76. ViewBag.Description = "Uh Oh, can't find it!";
  77. LogError(LogLevel.Warning, "Page Not Found");
  78. ErrorViewModel model = new ErrorViewModel();
  79. model.StatusCode = StatusCodes.Status404NotFound;
  80. return GenerateActionResult(CreateErrorObj("Http", StatusCodes.Status404NotFound, "Page Not Found"), View("~/Views/Error/Http404.cshtml", model));
  81. }
  82. [AllowAnonymous]
  83. public IActionResult Http500(Exception exception)
  84. {
  85. if (HttpContext != null)
  86. {
  87. var ex = HttpContext.Features.Get<IExceptionHandlerFeature>();
  88. if (ex != null)
  89. {
  90. exception = ex.Error;
  91. }
  92. HttpContext.Session.Set("Exception", exception);
  93. }
  94. Response.StatusCode = StatusCodes.Status500InternalServerError;
  95. ViewBag.Title = "500";
  96. ViewBag.Description = "Something Borked";
  97. LogError(LogLevel.Error, "Server Error", exception);
  98. ErrorViewModel model = new ErrorViewModel();
  99. model.StatusCode = StatusCodes.Status500InternalServerError;
  100. model.Exception = exception;
  101. return GenerateActionResult(CreateErrorObj("Http", StatusCodes.Status500InternalServerError, exception.Message), View("~/Views/Error/Http500.cshtml", model));
  102. }
  103. [AllowAnonymous]
  104. public async Task<IActionResult> IdentityError(string errorId)
  105. {
  106. var message = await _interaction.GetErrorContextAsync(errorId);
  107. Response.StatusCode = StatusCodes.Status500InternalServerError;
  108. ViewBag.Title = "Identity Error";
  109. ViewBag.Description = "The Identity Service threw an error";
  110. LogError(LogLevel.Error, "Identity Error: " + message.Error);
  111. IdentityErrorViewModel model = new IdentityErrorViewModel();
  112. model.Title = message.Error;
  113. model.Description = message.ErrorDescription;
  114. return GenerateActionResult(CreateErrorObj("Http", StatusCodes.Status500InternalServerError, message.Error), View("~/Views/Error/IdentityError.cshtml", model));
  115. }
  116. [HttpPost]
  117. [AllowAnonymous]
  118. [ValidateAntiForgeryToken]
  119. public IActionResult SubmitErrorReport(SubmitReportViewModel model)
  120. {
  121. try
  122. {
  123. string exceptionMsg = model.Exception;
  124. // Try to grab the actual exception that occured
  125. Exception ex = HttpContext.Session.Get<Exception>("Exception");
  126. if (ex != null)
  127. {
  128. exceptionMsg = string.Format(@"
  129. Exception: {0}
  130. Source: {1}
  131. Stack Trace:
  132. {2}
  133. ", ex.GetFullMessage(true), ex.Source, ex.StackTrace);
  134. }
  135. // Let's also email the message to support
  136. SmtpClient client = new SmtpClient();
  137. client.Host = _config.ContactConfig.EmailAccount.Host;
  138. client.Port = _config.ContactConfig.EmailAccount.Port;
  139. client.EnableSsl = _config.ContactConfig.EmailAccount.SSL;
  140. client.DeliveryMethod = SmtpDeliveryMethod.Network;
  141. client.UseDefaultCredentials = true;
  142. client.Credentials = new System.Net.NetworkCredential(_config.ContactConfig.EmailAccount.Username, _config.ContactConfig.EmailAccount.Password);
  143. client.Timeout = 5000;
  144. MailMessage mail = new MailMessage(new MailAddress(_config.NoReplyEmail, _config.NoReplyEmail), new MailAddress(_config.SupportEmail, "Teknik Support"));
  145. mail.Sender = new MailAddress(_config.ContactConfig.EmailAccount.EmailAddress);
  146. mail.Subject = "[Exception] Application Exception Occured";
  147. mail.Body = @"
  148. An exception has occured at: " + model.CurrentUrl + @"
  149. ----------------------------------------
  150. User Message:
  151. " + model.Message + @"
  152. ----------------------------------------
  153. " + exceptionMsg;
  154. mail.BodyEncoding = UTF8Encoding.UTF8;
  155. mail.DeliveryNotificationOptions = DeliveryNotificationOptions.Never;
  156. client.Send(mail);
  157. }
  158. catch (Exception ex)
  159. {
  160. return Json(new { error = "Error submitting report. Exception: " + ex.Message });
  161. }
  162. return Json(new { result = "true" });
  163. }
  164. private object CreateErrorObj(string type, int statusCode, string message)
  165. {
  166. return new { error = new { type = type, status = statusCode, message = message } };
  167. }
  168. private void LogError(LogLevel level, string message)
  169. {
  170. LogError(level, message, null);
  171. }
  172. private void LogError(LogLevel level, string message, Exception exception)
  173. {
  174. if (Request != null)
  175. {
  176. message += " | Url: " + Request.GetDisplayUrl();
  177. message += " | Referred Url: " + Request.Headers["Referer"].ToString();
  178. message += " | Method: " + Request.Method;
  179. message += " | User Agent: " + Request.Headers["User-Agent"].ToString();
  180. }
  181. _logger.Log(level, message, exception);
  182. }
  183. }
  184. }