2018-10-26 07:22:53 +02:00
|
|
|
|
using IdentityServer4.Services;
|
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
|
|
|
|
using Microsoft.AspNetCore.Diagnostics;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
using Microsoft.AspNetCore.Http.Extensions;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Net.Mail;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Teknik.Configuration;
|
|
|
|
|
using Teknik.IdentityServer.ViewModels;
|
|
|
|
|
using Teknik.Logging;
|
|
|
|
|
using Teknik.Utilities;
|
2021-07-01 06:56:12 +02:00
|
|
|
|
using Teknik.WebCommon;
|
2018-10-26 07:22:53 +02:00
|
|
|
|
|
|
|
|
|
namespace Teknik.IdentityServer.Controllers
|
|
|
|
|
{
|
2021-07-01 06:56:12 +02:00
|
|
|
|
public class ErrorController : DefaultController, IErrorController
|
2018-10-26 07:22:53 +02:00
|
|
|
|
{
|
|
|
|
|
private readonly IIdentityServerInteractionService _interaction;
|
|
|
|
|
|
|
|
|
|
public ErrorController(ILogger<Logger> logger, Config config, IIdentityServerInteractionService interaction) : base(logger, config)
|
|
|
|
|
{
|
|
|
|
|
_interaction = interaction;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-01 06:56:12 +02:00
|
|
|
|
[AllowAnonymous]
|
2018-10-26 07:22:53 +02:00
|
|
|
|
public IActionResult HttpError(int statusCode)
|
|
|
|
|
{
|
2021-07-01 06:56:12 +02:00
|
|
|
|
return HttpError(statusCode, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public IActionResult HttpError(int statusCode, Exception ex)
|
|
|
|
|
{
|
|
|
|
|
if (ex != null)
|
|
|
|
|
return Http500(ex);
|
|
|
|
|
|
2018-10-26 07:22:53 +02:00
|
|
|
|
switch (statusCode)
|
|
|
|
|
{
|
|
|
|
|
case 401:
|
|
|
|
|
return Http401();
|
|
|
|
|
case 403:
|
|
|
|
|
return Http403();
|
|
|
|
|
case 404:
|
|
|
|
|
return Http404();
|
2021-07-01 06:56:12 +02:00
|
|
|
|
case 500:
|
|
|
|
|
return Http500(ex);
|
2018-10-26 07:22:53 +02:00
|
|
|
|
default:
|
|
|
|
|
return HttpGeneral(statusCode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-01 06:56:12 +02:00
|
|
|
|
[AllowAnonymous]
|
2018-10-26 07:22:53 +02:00
|
|
|
|
public IActionResult HttpGeneral(int statusCode)
|
|
|
|
|
{
|
2019-01-26 06:16:01 +01:00
|
|
|
|
ViewBag.Title = statusCode;
|
2018-10-26 07:22:53 +02:00
|
|
|
|
|
|
|
|
|
LogError(LogLevel.Error, "HTTP Error Code: " + statusCode);
|
|
|
|
|
|
|
|
|
|
ErrorViewModel model = new ErrorViewModel();
|
|
|
|
|
model.StatusCode = statusCode;
|
|
|
|
|
|
|
|
|
|
return GenerateActionResult(CreateErrorObj("Http", statusCode, "Invalid HTTP Response"), View("~/Views/Error/HttpGeneral.cshtml", model));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public IActionResult Http401()
|
|
|
|
|
{
|
|
|
|
|
Response.StatusCode = StatusCodes.Status401Unauthorized;
|
|
|
|
|
|
2019-01-26 06:16:01 +01:00
|
|
|
|
ViewBag.Title = "401";
|
2018-10-26 07:22:53 +02:00
|
|
|
|
ViewBag.Description = "Unauthorized";
|
|
|
|
|
|
|
|
|
|
LogError(LogLevel.Error, "Unauthorized");
|
|
|
|
|
|
|
|
|
|
ErrorViewModel model = new ErrorViewModel();
|
|
|
|
|
model.StatusCode = StatusCodes.Status401Unauthorized;
|
|
|
|
|
|
|
|
|
|
return GenerateActionResult(CreateErrorObj("Http", StatusCodes.Status401Unauthorized, "Unauthorized"), View("~/Views/Error/Http401.cshtml", model));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public IActionResult Http403()
|
|
|
|
|
{
|
|
|
|
|
Response.StatusCode = StatusCodes.Status403Forbidden;
|
|
|
|
|
|
2019-01-26 06:16:01 +01:00
|
|
|
|
ViewBag.Title = "403";
|
2018-10-26 07:22:53 +02:00
|
|
|
|
ViewBag.Description = "Access Denied";
|
|
|
|
|
|
|
|
|
|
LogError(LogLevel.Error, "Access Denied");
|
|
|
|
|
|
|
|
|
|
ErrorViewModel model = new ErrorViewModel();
|
|
|
|
|
model.StatusCode = StatusCodes.Status403Forbidden;
|
|
|
|
|
|
|
|
|
|
return GenerateActionResult(CreateErrorObj("Http", StatusCodes.Status403Forbidden, "Access Denied"), View("~/Views/Error/Http403.cshtml", model));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public IActionResult Http404()
|
|
|
|
|
{
|
|
|
|
|
Response.StatusCode = StatusCodes.Status404NotFound;
|
|
|
|
|
|
2019-01-26 06:16:01 +01:00
|
|
|
|
ViewBag.Title = "404";
|
2018-10-26 07:22:53 +02:00
|
|
|
|
ViewBag.Description = "Uh Oh, can't find it!";
|
|
|
|
|
|
|
|
|
|
LogError(LogLevel.Warning, "Page Not Found");
|
|
|
|
|
|
|
|
|
|
ErrorViewModel model = new ErrorViewModel();
|
|
|
|
|
model.StatusCode = StatusCodes.Status404NotFound;
|
|
|
|
|
|
|
|
|
|
return GenerateActionResult(CreateErrorObj("Http", StatusCodes.Status404NotFound, "Page Not Found"), View("~/Views/Error/Http404.cshtml", model));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public IActionResult Http500(Exception exception)
|
|
|
|
|
{
|
|
|
|
|
if (HttpContext != null)
|
|
|
|
|
{
|
|
|
|
|
var ex = HttpContext.Features.Get<IExceptionHandlerFeature>();
|
|
|
|
|
if (ex != null)
|
|
|
|
|
{
|
|
|
|
|
exception = ex.Error;
|
|
|
|
|
}
|
|
|
|
|
HttpContext.Session.Set("Exception", exception);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Response.StatusCode = StatusCodes.Status500InternalServerError;
|
|
|
|
|
|
2019-01-26 06:16:01 +01:00
|
|
|
|
ViewBag.Title = "500";
|
2018-10-26 07:22:53 +02:00
|
|
|
|
ViewBag.Description = "Something Borked";
|
|
|
|
|
|
|
|
|
|
LogError(LogLevel.Error, "Server Error", exception);
|
|
|
|
|
|
|
|
|
|
ErrorViewModel model = new ErrorViewModel();
|
|
|
|
|
model.StatusCode = StatusCodes.Status500InternalServerError;
|
|
|
|
|
model.Exception = exception;
|
|
|
|
|
|
|
|
|
|
return GenerateActionResult(CreateErrorObj("Http", StatusCodes.Status500InternalServerError, exception.Message), View("~/Views/Error/Http500.cshtml", model));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public async Task<IActionResult> IdentityError(string errorId)
|
|
|
|
|
{
|
|
|
|
|
var message = await _interaction.GetErrorContextAsync(errorId);
|
|
|
|
|
|
|
|
|
|
Response.StatusCode = StatusCodes.Status500InternalServerError;
|
|
|
|
|
|
2019-01-26 06:16:01 +01:00
|
|
|
|
ViewBag.Title = "Identity Error";
|
2018-10-26 07:22:53 +02:00
|
|
|
|
ViewBag.Description = "The Identity Service threw an error";
|
|
|
|
|
|
2022-05-23 04:30:55 +02:00
|
|
|
|
LogError(LogLevel.Error, "Identity Error: " + message?.Error);
|
2018-10-26 07:22:53 +02:00
|
|
|
|
|
|
|
|
|
IdentityErrorViewModel model = new IdentityErrorViewModel();
|
2022-05-23 04:30:55 +02:00
|
|
|
|
model.Title = message?.Error;
|
2018-10-26 07:22:53 +02:00
|
|
|
|
model.Description = message.ErrorDescription;
|
|
|
|
|
|
|
|
|
|
return GenerateActionResult(CreateErrorObj("Http", StatusCodes.Status500InternalServerError, message.Error), View("~/Views/Error/IdentityError.cshtml", model));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HttpPost]
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
[ValidateAntiForgeryToken]
|
|
|
|
|
public IActionResult SubmitErrorReport(SubmitReportViewModel model)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
string exceptionMsg = model.Exception;
|
|
|
|
|
|
|
|
|
|
// Try to grab the actual exception that occured
|
|
|
|
|
Exception ex = HttpContext.Session.Get<Exception>("Exception");
|
|
|
|
|
if (ex != null)
|
|
|
|
|
{
|
|
|
|
|
exceptionMsg = string.Format(@"
|
|
|
|
|
Exception: {0}
|
|
|
|
|
|
|
|
|
|
Source: {1}
|
|
|
|
|
|
|
|
|
|
Stack Trace:
|
|
|
|
|
|
|
|
|
|
{2}
|
|
|
|
|
", ex.GetFullMessage(true), ex.Source, ex.StackTrace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Let's also email the message to support
|
|
|
|
|
SmtpClient client = new SmtpClient();
|
|
|
|
|
client.Host = _config.ContactConfig.EmailAccount.Host;
|
|
|
|
|
client.Port = _config.ContactConfig.EmailAccount.Port;
|
|
|
|
|
client.EnableSsl = _config.ContactConfig.EmailAccount.SSL;
|
|
|
|
|
client.DeliveryMethod = SmtpDeliveryMethod.Network;
|
|
|
|
|
client.Credentials = new System.Net.NetworkCredential(_config.ContactConfig.EmailAccount.Username, _config.ContactConfig.EmailAccount.Password);
|
|
|
|
|
client.Timeout = 5000;
|
|
|
|
|
|
|
|
|
|
MailMessage mail = new MailMessage(new MailAddress(_config.NoReplyEmail, _config.NoReplyEmail), new MailAddress(_config.SupportEmail, "Teknik Support"));
|
|
|
|
|
mail.Sender = new MailAddress(_config.ContactConfig.EmailAccount.EmailAddress);
|
|
|
|
|
mail.Subject = "[Exception] Application Exception Occured";
|
|
|
|
|
mail.Body = @"
|
|
|
|
|
An exception has occured at: " + model.CurrentUrl + @"
|
|
|
|
|
|
|
|
|
|
----------------------------------------
|
|
|
|
|
User Message:
|
|
|
|
|
|
|
|
|
|
" + model.Message + @"
|
|
|
|
|
|
|
|
|
|
----------------------------------------
|
|
|
|
|
" + exceptionMsg;
|
|
|
|
|
mail.BodyEncoding = UTF8Encoding.UTF8;
|
|
|
|
|
mail.DeliveryNotificationOptions = DeliveryNotificationOptions.Never;
|
|
|
|
|
|
|
|
|
|
client.Send(mail);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
return Json(new { error = "Error submitting report. Exception: " + ex.Message });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Json(new { result = "true" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private object CreateErrorObj(string type, int statusCode, string message)
|
|
|
|
|
{
|
|
|
|
|
return new { error = new { type = type, status = statusCode, message = message } };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void LogError(LogLevel level, string message)
|
|
|
|
|
{
|
|
|
|
|
LogError(level, message, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void LogError(LogLevel level, string message, Exception exception)
|
|
|
|
|
{
|
|
|
|
|
if (Request != null)
|
|
|
|
|
{
|
|
|
|
|
message += " | Url: " + Request.GetDisplayUrl();
|
|
|
|
|
|
|
|
|
|
message += " | Referred Url: " + Request.Headers["Referer"].ToString();
|
|
|
|
|
|
|
|
|
|
message += " | Method: " + Request.Method;
|
|
|
|
|
|
|
|
|
|
message += " | User Agent: " + Request.Headers["User-Agent"].ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_logger.Log(level, message, exception);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|