Browse Source

Made tracking operations go to a background queue to be processed.

tags/5.0.0
Teknikode 2 years ago
parent
commit
89ba60b593
31 changed files with 292 additions and 111 deletions
  1. 1
    1
      Teknik/Areas/API/V1/Controllers/AccountAPIv1Controller.cs
  2. 1
    1
      Teknik/Areas/API/V1/Controllers/PasteAPIv1Controller.cs
  3. 1
    1
      Teknik/Areas/API/V1/Controllers/ShortenAPIv1Controller.cs
  4. 1
    1
      Teknik/Areas/API/V1/Controllers/UploadAPIv1Controller.cs
  5. 1
    1
      Teknik/Areas/About/Controllers/AboutController.cs
  6. 1
    1
      Teknik/Areas/Abuse/Controllers/AbuseController.cs
  7. 4
    4
      Teknik/Areas/Admin/Controllers/AdminController.cs
  8. 4
    4
      Teknik/Areas/Blog/Controllers/BlogController.cs
  9. 1
    1
      Teknik/Areas/Contact/Controllers/ContactController.cs
  10. 6
    6
      Teknik/Areas/Error/Controllers/ErrorController.cs
  11. 1
    1
      Teknik/Areas/FAQ/Controllers/FAQController.cs
  12. 1
    1
      Teknik/Areas/Help/Controllers/HelpController.cs
  13. 1
    1
      Teknik/Areas/Home/Controllers/HomeController.cs
  14. 3
    3
      Teknik/Areas/Paste/Controllers/PasteController.cs
  15. 3
    3
      Teknik/Areas/Podcast/Controllers/PodcastController.cs
  16. 1
    1
      Teknik/Areas/Privacy/Controllers/PrivacyController.cs
  17. 3
    3
      Teknik/Areas/RSS/Controllers/RSSController.cs
  18. 2
    2
      Teknik/Areas/Shortener/Controllers/ShortenerController.cs
  19. 1
    1
      Teknik/Areas/Stats/Controllers/StatsController.cs
  20. 1
    1
      Teknik/Areas/TOS/Controllers/TOSController.cs
  21. 3
    3
      Teknik/Areas/Upload/Controllers/UploadController.cs
  22. 17
    17
      Teknik/Areas/User/Controllers/UserController.cs
  23. 4
    4
      Teknik/Areas/Vault/Controllers/VaultController.cs
  24. 31
    18
      Teknik/Filters/TrackDownload.cs
  25. 40
    29
      Teknik/Filters/TrackPageView.cs
  26. 6
    2
      Teknik/Startup.cs
  27. 2
    0
      Tracking/Tracking.csproj
  28. 48
    0
      Tracking/TrackingService.cs
  29. 38
    0
      Utilities/BackgroundTaskQueue.cs
  30. 49
    0
      Utilities/HostedService.cs
  31. 16
    0
      Utilities/IBackgroundTaskQueue.cs

+ 1
- 1
Teknik/Areas/API/V1/Controllers/AccountAPIv1Controller.cs View File

@@ -19,7 +19,7 @@ namespace Teknik.Areas.API.V1.Controllers
public AccountAPIv1Controller(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }

[HttpGet]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult GetClaims()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });

+ 1
- 1
Teknik/Areas/API/V1/Controllers/PasteAPIv1Controller.cs View File

@@ -25,7 +25,7 @@ namespace Teknik.Areas.API.V1.Controllers

[HttpPost]
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Paste(PasteAPIv1Model model)
{
try

+ 1
- 1
Teknik/Areas/API/V1/Controllers/ShortenAPIv1Controller.cs View File

@@ -26,7 +26,7 @@ namespace Teknik.Areas.API.V1.Controllers

[HttpPost]
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Shorten(ShortenAPIv1Model model)
{
try

+ 1
- 1
Teknik/Areas/API/V1/Controllers/UploadAPIv1Controller.cs View File

@@ -30,7 +30,7 @@ namespace Teknik.Areas.API.V1.Controllers

[HttpPost]
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> Upload(UploadAPIv1Model model)
{
try

+ 1
- 1
Teknik/Areas/About/Controllers/AboutController.cs View File

@@ -22,7 +22,7 @@ namespace Teknik.Areas.About.Controllers
public AboutController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }

[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index([FromServices] Config config)
{
ViewBag.Title = "About";

+ 1
- 1
Teknik/Areas/Abuse/Controllers/AbuseController.cs View File

@@ -22,7 +22,7 @@ namespace Teknik.Areas.Abuse.Controllers
public AbuseController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index()
{
ViewBag.Title = "Abuse Reporting";

+ 4
- 4
Teknik/Areas/Admin/Controllers/AdminController.cs View File

@@ -29,7 +29,7 @@ namespace Teknik.Areas.Admin.Controllers
public AdminController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base (logger, config, dbContext) { }

[HttpGet]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Dashboard()
{
DashboardViewModel model = new DashboardViewModel();
@@ -37,7 +37,7 @@ namespace Teknik.Areas.Admin.Controllers
}

[HttpGet]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult UserSearch()
{
UserSearchViewModel model = new UserSearchViewModel();
@@ -45,7 +45,7 @@ namespace Teknik.Areas.Admin.Controllers
}

[HttpGet]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> UserInfo(string username)
{
if (UserHelper.UserExists(_dbContext, username))
@@ -66,7 +66,7 @@ namespace Teknik.Areas.Admin.Controllers
}

[HttpGet]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult UploadSearch()
{
UploadSearchViewModel model = new UploadSearchViewModel();

+ 4
- 4
Teknik/Areas/Blog/Controllers/BlogController.cs View File

@@ -30,7 +30,7 @@ namespace Teknik.Areas.Blog.Controllers
public BlogController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Blog(string username)
{
BlogViewModel model = new BlogViewModel();
@@ -120,7 +120,7 @@ namespace Teknik.Areas.Blog.Controllers

#region Posts
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Post(string username, int id)
{
if (string.IsNullOrEmpty(username))
@@ -163,7 +163,7 @@ namespace Teknik.Areas.Blog.Controllers
return View("~/Areas/Blog/Views/Blog/ViewPost.cshtml", model);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult NewPost(string username, int blogID)
{
if (string.IsNullOrEmpty(username))
@@ -203,7 +203,7 @@ namespace Teknik.Areas.Blog.Controllers
return View("~/Areas/Blog/Views/Blog/Blog.cshtml", model);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult EditPost(string username, int id)
{
if (string.IsNullOrEmpty(username))

+ 1
- 1
Teknik/Areas/Contact/Controllers/ContactController.cs View File

@@ -26,7 +26,7 @@ namespace Teknik.Areas.Contact.Controllers
public ContactController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index()
{
ViewBag.Title = "Contact Us";

+ 6
- 6
Teknik/Areas/Error/Controllers/ErrorController.cs View File

@@ -28,7 +28,7 @@ namespace Teknik.Areas.Error.Controllers
public ErrorController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }

[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult HttpError(int statusCode)
{
switch (statusCode)
@@ -45,7 +45,7 @@ namespace Teknik.Areas.Error.Controllers
}

[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult HttpGeneral(int statusCode)
{
ViewBag.Title = statusCode;
@@ -59,7 +59,7 @@ namespace Teknik.Areas.Error.Controllers
}

[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Http401()
{
Response.StatusCode = StatusCodes.Status401Unauthorized;
@@ -76,7 +76,7 @@ namespace Teknik.Areas.Error.Controllers
}

[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Http403()
{
Response.StatusCode = StatusCodes.Status403Forbidden;
@@ -93,7 +93,7 @@ namespace Teknik.Areas.Error.Controllers
}

[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Http404()
{
Response.StatusCode = StatusCodes.Status404NotFound;
@@ -110,7 +110,7 @@ namespace Teknik.Areas.Error.Controllers
}
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Http500(Exception exception)
{
try

+ 1
- 1
Teknik/Areas/FAQ/Controllers/FAQController.cs View File

@@ -18,7 +18,7 @@ namespace Teknik.Areas.FAQ.Controllers
public FAQController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index()
{
ViewBag.Title = "Frequently Asked Questions";

+ 1
- 1
Teknik/Areas/Help/Controllers/HelpController.cs View File

@@ -14,7 +14,7 @@ namespace Teknik.Areas.Help.Controllers
{
[Authorize]
[Area("Help")]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public class HelpController : DefaultController
{
public HelpController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }

+ 1
- 1
Teknik/Areas/Home/Controllers/HomeController.cs View File

@@ -23,7 +23,7 @@ namespace Teknik.Areas.Home.Controllers
public HomeController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index()
{
HomeViewModel model = new HomeViewModel();

+ 3
- 3
Teknik/Areas/Paste/Controllers/PasteController.cs View File

@@ -31,7 +31,7 @@ namespace Teknik.Areas.Paste.Controllers
public PasteController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index()
{
ViewBag.Title = "Pastebin";
@@ -41,7 +41,7 @@ namespace Teknik.Areas.Paste.Controllers
}
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> ViewPaste(string type, string url, string password)
{
Models.Paste paste = _dbContext.Pastes.Where(p => p.Url == url).FirstOrDefault();
@@ -205,7 +205,7 @@ namespace Teknik.Areas.Paste.Controllers
return View("~/Areas/Paste/Views/Paste/Index.cshtml", model);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> Edit(string url, string password)
{
Models.Paste paste = _dbContext.Pastes.Where(p => p.Url == url).FirstOrDefault();

+ 3
- 3
Teknik/Areas/Podcast/Controllers/PodcastController.cs View File

@@ -29,7 +29,7 @@ namespace Teknik.Areas.Podcast.Controllers
public PodcastController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index()
{
MainViewModel model = new MainViewModel();
@@ -64,7 +64,7 @@ namespace Teknik.Areas.Podcast.Controllers

#region Podcasts
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult View(int episode)
{
PodcastViewModel model = new PodcastViewModel();
@@ -86,7 +86,7 @@ namespace Teknik.Areas.Podcast.Controllers
[HttpGet]
[AllowAnonymous]
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any)]
[ServiceFilter(typeof(TrackDownload))]
[TrackDownload]
public IActionResult Download(int episode, string fileName)
{
string path = string.Empty;

+ 1
- 1
Teknik/Areas/Privacy/Controllers/PrivacyController.cs View File

@@ -18,7 +18,7 @@ namespace Teknik.Areas.Privacy.Controllers
public PrivacyController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index()
{
ViewBag.Title = "Privacy Policy";

+ 3
- 3
Teknik/Areas/RSS/Controllers/RSSController.cs View File

@@ -32,7 +32,7 @@ namespace Teknik.Areas.RSS.Controllers
public RSSController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task Index()
{
Response.ContentType = "application/rss+xml";
@@ -50,7 +50,7 @@ namespace Teknik.Areas.RSS.Controllers
}
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task Blog(string username)
{
Response.ContentType = "application/rss+xml";
@@ -156,7 +156,7 @@ namespace Teknik.Areas.RSS.Controllers
}
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task Podcast()
{
Response.ContentType = "application/rss+xml";

+ 2
- 2
Teknik/Areas/Shortener/Controllers/ShortenerController.cs View File

@@ -24,7 +24,7 @@ namespace Teknik.Areas.Shortener.Controllers
public ShortenerController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index()
{
ViewBag.Title = "Url Shortener";
@@ -33,7 +33,7 @@ namespace Teknik.Areas.Shortener.Controllers
}
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult RedirectToUrl(string url)
{
ShortenedUrl shortUrl = _dbContext.ShortenedUrls.Where(s => s.ShortUrl == url).FirstOrDefault();

+ 1
- 1
Teknik/Areas/Stats/Controllers/StatsController.cs View File

@@ -24,7 +24,7 @@ namespace Teknik.Areas.Stats.Controllers
public StatsController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index()
{
ViewBag.Title = "System Statistics";

+ 1
- 1
Teknik/Areas/TOS/Controllers/TOSController.cs View File

@@ -18,7 +18,7 @@ namespace Teknik.Areas.TOS.Controllers
public TOSController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Index()
{
ViewBag.Title = "Terms of Service";

+ 3
- 3
Teknik/Areas/Upload/Controllers/UploadController.cs View File

@@ -33,7 +33,7 @@ namespace Teknik.Areas.Upload.Controllers
[HttpGet]
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> Index()
{
ViewBag.Title = "Upload Files";
@@ -181,8 +181,8 @@ namespace Teknik.Areas.Upload.Controllers
[HttpGet]
[AllowAnonymous]
[ServiceFilter(typeof(TrackDownload))]
[ServiceFilter(typeof(TrackPageView))]
[TrackDownload]
[TrackPageView]
[ResponseCache(Duration = 31536000, Location = ResponseCacheLocation.Any)]
public async Task<IActionResult> Download(string file)
{

+ 17
- 17
Teknik/Areas/User/Controllers/UserController.cs View File

@@ -62,7 +62,7 @@ namespace Teknik.Areas.Users.Controllers
}

[HttpGet]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Login(string returnUrl)
{
// Let's double check their email and git accounts to make sure they exist
@@ -86,7 +86,7 @@ namespace Teknik.Areas.Users.Controllers
}

[HttpGet]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task Logout()
{
// these are the sub & sid to signout
@@ -100,7 +100,7 @@ namespace Teknik.Areas.Users.Controllers
}

[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult GetPremium()
{
ViewBag.Title = "Get a Premium Account";
@@ -112,7 +112,7 @@ namespace Teknik.Areas.Users.Controllers

[HttpGet]
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Register(string inviteCode, string ReturnUrl)
{
RegisterViewModel model = new RegisterViewModel();
@@ -206,7 +206,7 @@ namespace Teknik.Areas.Users.Controllers

// GET: Profile/Profile
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> ViewProfile(string username)
{
if (string.IsNullOrEmpty(username))
@@ -264,7 +264,7 @@ namespace Teknik.Areas.Users.Controllers
return View(model);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult ViewServiceData()
{
string username = User.Identity.Name;
@@ -303,13 +303,13 @@ namespace Teknik.Areas.Users.Controllers
return View(model);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult Settings()
{
return Redirect(Url.SubRouteUrl("account", "User.ProfileSettings"));
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult ProfileSettings()
{
string username = User.Identity.Name;
@@ -334,7 +334,7 @@ namespace Teknik.Areas.Users.Controllers
return new StatusCodeResult(StatusCodes.Status403Forbidden);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult AccountSettings()
{
string username = User.Identity.Name;
@@ -356,7 +356,7 @@ namespace Teknik.Areas.Users.Controllers
return new StatusCodeResult(StatusCodes.Status403Forbidden);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> SecuritySettings()
{
string username = User.Identity.Name;
@@ -399,7 +399,7 @@ namespace Teknik.Areas.Users.Controllers
return new StatusCodeResult(StatusCodes.Status403Forbidden);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> DeveloperSettings()
{
string username = User.Identity.Name;
@@ -447,7 +447,7 @@ namespace Teknik.Areas.Users.Controllers
return new StatusCodeResult(StatusCodes.Status403Forbidden);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult InviteSettings()
{
string username = User.Identity.Name;
@@ -493,7 +493,7 @@ namespace Teknik.Areas.Users.Controllers
return new StatusCodeResult(StatusCodes.Status403Forbidden);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult BlogSettings()
{
string username = User.Identity.Name;
@@ -517,7 +517,7 @@ namespace Teknik.Areas.Users.Controllers
return new StatusCodeResult(StatusCodes.Status403Forbidden);
}

[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult UploadSettings()
{
string username = User.Identity.Name;
@@ -544,7 +544,7 @@ namespace Teknik.Areas.Users.Controllers

[HttpGet]
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> ViewRawPGP(string username)
{
ViewBag.Title = username + "'s Public Key";
@@ -839,7 +839,7 @@ namespace Teknik.Areas.Users.Controllers

[HttpGet]
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult ResetPassword(string username)
{
ResetPasswordViewModel model = new ResetPasswordViewModel();
@@ -883,7 +883,7 @@ namespace Teknik.Areas.Users.Controllers

[HttpGet]
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> VerifyResetPassword(string username, string code)
{
bool verified = true;

+ 4
- 4
Teknik/Areas/Vault/Controllers/VaultController.cs View File

@@ -34,7 +34,7 @@ namespace Teknik.Areas.Vault.Controllers
public VaultController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public async Task<IActionResult> ViewVault(string id)
{
Models.Vault foundVault = _dbContext.Vaults.Where(v => v.Url == id).FirstOrDefault();
@@ -136,7 +136,7 @@ namespace Teknik.Areas.Vault.Controllers

[HttpGet]
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult NewVault()
{
ViewBag.Title = "Create Vault";
@@ -147,7 +147,7 @@ namespace Teknik.Areas.Vault.Controllers

[HttpGet]
[AllowAnonymous]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult NewVaultFromService(string type, string items)
{
ViewBag.Title = "Create Vault";
@@ -184,7 +184,7 @@ namespace Teknik.Areas.Vault.Controllers
}

[HttpGet]
[ServiceFilter(typeof(TrackPageView))]
[TrackPageView]
public IActionResult EditVault(string url, string type, string items)
{
ViewBag.Title = "Edit Vault";

+ 31
- 18
Teknik/Filters/TrackDownload.cs View File

@@ -10,39 +10,52 @@ using Teknik.Tracking;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;

namespace Teknik.Filters
{
public class TrackDownload : ActionFilterAttribute
public class TrackDownloadAttribute : TypeFilterAttribute
{
private readonly Config _config;

public TrackDownload(Config config)
public TrackDownloadAttribute() : base(typeof(TrackDownload))
{
_config = config;
}

public override void OnActionExecuting(ActionExecutingContext filterContext)
public class TrackDownload : ActionFilterAttribute
{
}
private readonly IBackgroundTaskQueue _queue;
private readonly Config _config;

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
HttpRequest request = filterContext.HttpContext.Request;
public TrackDownload(IBackgroundTaskQueue queue, Config config)
{
_queue = queue;
_config = config;
}

string doNotTrack = request.Headers["DNT"];
if (string.IsNullOrEmpty(doNotTrack) || doNotTrack != "1")
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string userAgent = request.Headers["User-Agent"].ToString();
}

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
HttpRequest request = filterContext.HttpContext.Request;

string doNotTrack = request.Headers["DNT"];
if (string.IsNullOrEmpty(doNotTrack) || doNotTrack != "1")
{
string userAgent = request.Headers["User-Agent"].ToString();

string clientIp = request.ClientIPFromRequest(true);
string clientIp = request.ClientIPFromRequest(true);

string urlReferrer = request.Headers["Referer"].ToString();
string urlReferrer = request.Headers["Referer"].ToString();

string url = UriHelper.GetEncodedUrl(request);
string url = UriHelper.GetEncodedUrl(request);

// Fire and forget. Don't need to wait for it.
Tracking.Tracking.TrackDownload(filterContext.HttpContext, _config, userAgent, clientIp, url, urlReferrer);
// Fire and forget. Don't need to wait for it.
_queue.QueueBackgroundWorkItem(async token =>
{
Tracking.Tracking.TrackDownload(filterContext.HttpContext, _config, userAgent, clientIp, url, urlReferrer);
});
}
}
}
}

+ 40
- 29
Teknik/Filters/TrackPageView.cs View File

@@ -14,53 +14,64 @@ using Microsoft.AspNetCore.Mvc;

namespace Teknik.Filters
{
public class TrackPageView : ActionFilterAttribute
public class TrackPageViewAttribute : TypeFilterAttribute
{
private readonly Config _config;

public TrackPageView(Config config)
public TrackPageViewAttribute() : base(typeof(TrackPageView))
{
_config = config;
}

public override void OnActionExecuting(ActionExecutingContext filterContext)
public class TrackPageView : ActionFilterAttribute
{
}
private readonly IBackgroundTaskQueue _queue;
private readonly Config _config;

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
HttpRequest request = filterContext.HttpContext.Request;
public TrackPageView(IBackgroundTaskQueue queue, Config config)
{
_queue = queue;
_config = config;
}

string doNotTrack = request.Headers["DNT"];
if (string.IsNullOrEmpty(doNotTrack) || doNotTrack != "1")
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string title = (filterContext.Controller as Controller)?.ViewBag?.Title;
}

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
HttpRequest request = filterContext.HttpContext.Request;

string sub = filterContext.RouteData.Values["sub"].ToString();
if (string.IsNullOrEmpty(sub))
string doNotTrack = request.Headers["DNT"];
if (string.IsNullOrEmpty(doNotTrack) || doNotTrack != "1")
{
sub = request.Host.ToUriComponent().GetSubdomain();
}
string title = (filterContext.Controller as Controller)?.ViewBag?.Title;

string sub = filterContext.RouteData.Values["sub"].ToString();
if (string.IsNullOrEmpty(sub))
{
sub = request.Host.ToUriComponent().GetSubdomain();
}

string clientIp = request.ClientIPFromRequest(true);
string clientIp = request.ClientIPFromRequest(true);

string url = UriHelper.GetEncodedUrl(request);
string url = UriHelper.GetEncodedUrl(request);

string urlReferrer = request.Headers["Referer"].ToString();
string urlReferrer = request.Headers["Referer"].ToString();

string userAgent = request.Headers["User-Agent"].ToString();
string userAgent = request.Headers["User-Agent"].ToString();

int pixelWidth = 0;
int pixelHeight = 0;
int pixelWidth = 0;
int pixelHeight = 0;

bool hasCookies = false;
bool hasCookies = false;

string acceptLang = request.Headers["Accept-Language"];
string acceptLang = request.Headers["Accept-Language"];

bool hasJava = false;
bool hasJava = false;

// Fire and forget. Don't need to wait for it.
Tracking.Tracking.TrackPageView(filterContext.HttpContext, _config, title, sub, clientIp, url, urlReferrer, userAgent, pixelWidth, pixelHeight, hasCookies, acceptLang, hasJava);
// Fire and forget. Don't need to wait for it.
_queue.QueueBackgroundWorkItem(async token =>
{
Tracking.Tracking.TrackPageView(filterContext.HttpContext, _config, title, sub, clientIp, url, urlReferrer, userAgent, pixelWidth, pixelHeight, hasCookies, acceptLang, hasJava);
});
}
}
}
}

+ 6
- 2
Teknik/Startup.cs View File

@@ -39,6 +39,7 @@ using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Authorization;
using System.Text.Encodings.Web;
using Teknik.Tracking;

namespace Teknik
{
@@ -96,10 +97,13 @@ namespace Teknik
#endif
});

services.AddHostedService<TrackingService>();
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();

// Add Tracking Filter scopes
services.AddScoped<TrackDownload>();
//services.AddScoped<TrackDownload>();
//services.AddScoped<TrackLink>();
services.AddScoped<TrackPageView>();
//services.AddScoped<TrackPageView>();

// Create the Database Context
services.AddDbContext<TeknikEntities>(options => options

+ 2
- 0
Tracking/Tracking.csproj View File

@@ -13,6 +13,8 @@

<ItemGroup>
<ProjectReference Include="..\Configuration\Configuration.csproj" />
<ProjectReference Include="..\Logging\Logging.csproj" />
<ProjectReference Include="..\Utilities\Utilities.csproj" />
</ItemGroup>

<ItemGroup>

+ 48
- 0
Tracking/TrackingService.cs View File

@@ -0,0 +1,48 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Teknik.Logging;
using Teknik.Utilities;

namespace Teknik.Tracking
{
public class TrackingService : BackgroundService
{
private readonly ILogger<Logger> _logger;

public TrackingService(IBackgroundTaskQueue taskQueue,
ILogger<Logger> logger)
{
TaskQueue = taskQueue;
_logger = logger;
}

public IBackgroundTaskQueue TaskQueue { get; }

protected async override Task ExecuteAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Queued Hosted Service is starting.");

while (!cancellationToken.IsCancellationRequested)
{
var workItem = await TaskQueue.DequeueAsync(cancellationToken);

try
{
await workItem(cancellationToken);
}
catch (Exception ex)
{
_logger.LogError(ex,
$"Error occurred executing {nameof(workItem)}.");
}
}

_logger.LogInformation("Queued Hosted Service is stopping.");
}
}
}

+ 38
- 0
Utilities/BackgroundTaskQueue.cs View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Teknik.Utilities
{
public class BackgroundTaskQueue : IBackgroundTaskQueue
{
private ConcurrentQueue<Func<CancellationToken, Task>> _workItems =
new ConcurrentQueue<Func<CancellationToken, Task>>();

private SemaphoreSlim _signal = new SemaphoreSlim(0);

public void QueueBackgroundWorkItem(
Func<CancellationToken, Task> workItem)
{
if (workItem == null)
{
throw new ArgumentNullException(nameof(workItem));
}

_workItems.Enqueue(workItem);
_signal.Release();
}

public async Task<Func<CancellationToken, Task>> DequeueAsync(
CancellationToken cancellationToken)
{
await _signal.WaitAsync(cancellationToken);
_workItems.TryDequeue(out var workItem);

return workItem;
}
}
}

+ 49
- 0
Utilities/HostedService.cs View File

@@ -0,0 +1,49 @@
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Teknik.Utilities
{
public abstract class HostedService : IHostedService
{
private Task _executingTask;
private CancellationTokenSource _cts;

public Task StartAsync(CancellationToken cancellationToken)
{
// Create a linked token so we can trigger cancellation outside of this token's cancellation
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

// Store the task we're executing
_executingTask = ExecuteAsync(_cts.Token);

// If the task is completed then return it, otherwise it's running
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
}

public async Task StopAsync(CancellationToken cancellationToken)
{
// Stop called without start
if (_executingTask == null)
{
return;
}

// Signal cancellation to the executing method
_cts.Cancel();

// Wait until the task completes or the stop token triggers
await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken));

// Throw if cancellation triggered
cancellationToken.ThrowIfCancellationRequested();
}

// Derived classes should override this and execute a long running method until
// cancellation is requested
protected abstract Task ExecuteAsync(CancellationToken cancellationToken);
}
}

+ 16
- 0
Utilities/IBackgroundTaskQueue.cs View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Teknik.Utilities
{
public interface IBackgroundTaskQueue
{
void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem);

Task<Func<CancellationToken, Task>> DequeueAsync(
CancellationToken cancellationToken);
}
}

Loading…
Cancel
Save