Upgraded blog script to "Blog System 2.2"

  Annice      2020-11-28      Updates, C#, ASP.NET Core

I have now upgraded the C# script "Blog System 2.0" to version 2.2. The new script "Blog System 2.2" is also availble to download from the script page.

From now on, the script ensures that anonymous users cannot navigate to an entry ID having the status set to "draft", i.e. an unpublished blog entry.

The authentication in this script is mainly handled via a middleware that senses specific names of controllers through every HTTP request for different admin pages. In other words, the auth server ensures via the middleware that controllers rendering admin pages will not display these pages for unauthorized users. Moreover, the code snippet below that handles this control can be found in the script file "AuthServer.cs" in the folder "Middleware":

public async Task InvokeAsync(HttpContext context, [FromServices] IAuthHandler handler)
{
  string[] paths = { "/Entry", "/Comment", "/Category", "/User" };

  foreach(string path in paths)
  {
    if (!handler.IsLoggedIn() && context.Request.Path.ToString().StartsWith(path))
    {
      context.Response.StatusCode = 401; // Unauthorized.
      context.Response.Redirect(context.Request.Scheme + "://" + context.Request.Host + "/Home/AccessDenied");
      return;
    }
  }

  await _next.Invoke(context);
}


Simultaneously, an auth handler service is called to ensure these controllers are always accessible by a logged in admin. In turn, this auth handler checks whether a session variable is set that has temporarily saved the admin's user ID after a valid login. The control method that is being called by the auth server above and that controls whether this session value exists or not can also be found in the file "AuthHandler.cs" in the script folder "Services":

public bool IsLoggedIn()
{
  var scope = _scope.CreateScope();
  var context = scope.ServiceProvider.GetService <IHttpContextAccessor>();

  // If user session is set, it means we have a valid login:
  if (context.HttpContext.Session.GetString("UserID") != null)
      return true;
  else
     return false;
}


Moreover, the controller handling the public pages in this blog system is called "HomeController". This is also the controller handling every entry detail page, i.e. where you can see an entry in its entirety as well as where visitors can leave comments.

Also, as this controller handles these detail pages regardless if they are drafts or published - while the controller name "Home" is not sensed by the auth server - a check has now been added to this controller to ensure only admins can see draft entries. This was done by adding a condition in the action method "EntryComments", which renders detail pages according to the code snippet below:

[HttpGet]
public IActionResult EntryComments(int? id)
{
  // Catch posted feedback:
  ViewBag.Success = TempData["Success"];
 
  // Check valid admin login if draft entry:
  if (HttpContext.Session.GetString("UserID") == null &&
      _db.BsEntries.Where(e =>e.Id == id && e.IsPublished == false).Any())
  {
    return RedirectToAction(nameof(Index));
  }

  // ...


The condition in the if statement above is now checking if the admin session is unkown at the same time as the requested entry ID is checked to be a draft. In that case, the visitor will be interpreted as an anonymous user and therefore just redirected to the public start page, i.e. never access the requested entry. Moreover, the added code illustrated above can be found in its full context in the script file "HomeController.cs" in the folder "Controllers".