diff --git a/Providers/Resgrid.Providers.MigrationsPg/Resgrid.Providers.MigrationsPg.csproj b/Providers/Resgrid.Providers.MigrationsPg/Resgrid.Providers.MigrationsPg.csproj
index 191b58a61..7025c4567 100644
--- a/Providers/Resgrid.Providers.MigrationsPg/Resgrid.Providers.MigrationsPg.csproj
+++ b/Providers/Resgrid.Providers.MigrationsPg/Resgrid.Providers.MigrationsPg.csproj
@@ -26,6 +26,7 @@
+
diff --git a/Web/Resgrid.Web/Controllers/AccountController.cs b/Web/Resgrid.Web/Controllers/AccountController.cs
index fec0099b2..b545dff4f 100644
--- a/Web/Resgrid.Web/Controllers/AccountController.cs
+++ b/Web/Resgrid.Web/Controllers/AccountController.cs
@@ -23,6 +23,8 @@
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using Microsoft.AspNetCore.Localization;
+using static Microsoft.ApplicationInsights.MetricDimensionNames.TelemetryContext;
+using PostHog;
namespace Resgrid.Web.Controllers
{
@@ -45,12 +47,14 @@ public class AccountController : Controller
private readonly IEmailMarketingProvider _emailMarketingProvider;
private readonly ISystemAuditsService _systemAuditsService;
private readonly ICacheProvider _cacheProvider;
-
+ private readonly IPostHogClient _posthog;
+
+
public AccountController(
UserManager userManager, SignInManager signInManager,
IDepartmentsService departmentsService, IUsersService usersService, IEmailService emailService, IInvitesService invitesService, IUserProfileService userProfileService,
ISubscriptionsService subscriptionsService, IAffiliateService affiliateService, IEventAggregator eventAggregator, IEmailMarketingProvider emailMarketingProvider,
- ISystemAuditsService systemAuditsService, ICacheProvider cacheProvider)
+ ISystemAuditsService systemAuditsService, ICacheProvider cacheProvider, IPostHogClient posthog)
{
_userManager = userManager;
_signInManager = signInManager;
@@ -65,6 +69,7 @@ public AccountController(
_emailMarketingProvider = emailMarketingProvider;
_systemAuditsService = systemAuditsService;
_cacheProvider = cacheProvider;
+ _posthog = posthog;
}
#endregion Private Members and Constructors
@@ -128,6 +133,29 @@ await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
{
var token = await ApiAuthHelper.GetBearerApiTokenAsync(model.Username, model.Password);
await _cacheProvider.SetStringAsync(CacheConfig.ApiBearerTokenKeyName + $"_${userId}", token, new TimeSpan(48, 0, 0));
+
+ if (!String.IsNullOrWhiteSpace(TelemetryConfig.PostHogApiKey))
+ {
+ var email = User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value;
+ var departmentId = User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.PrimaryGroupSid)?.Value;
+ var departmentName = User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Actor)?.Value;
+ var name = User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.GivenName)?.Value;
+ var createdOn = User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.OtherPhone)?.Value;
+
+ await _posthog.IdentifyAsync(
+ userId,
+ email,
+ name,
+ personPropertiesToSet: new()
+ {
+ ["departmentId"] = departmentId,
+ ["departmentName"] = departmentName,
+ },
+ personPropertiesToSetOnce: new()
+ {
+ ["createdOn"] = createdOn
+ });
+ }
}
}
catch (Exception ex)
@@ -139,7 +167,7 @@ await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
Response.Cookies.Delete(".AspNetCore.Identity.ApplicationC1");
Response.Cookies.Delete(".AspNetCore.Identity.ApplicationC2");
Response.Cookies.Delete(".AspNetCore.Identity.ApplicationC3");
-
+
if (!String.IsNullOrWhiteSpace(returnUrl))
return RedirectToLocal(returnUrl);
else
diff --git a/Web/Resgrid.Web/Middleware/FeatureFlagContextProvider.cs b/Web/Resgrid.Web/Middleware/FeatureFlagContextProvider.cs
new file mode 100644
index 000000000..e622ddae3
--- /dev/null
+++ b/Web/Resgrid.Web/Middleware/FeatureFlagContextProvider.cs
@@ -0,0 +1,36 @@
+using Microsoft.AspNetCore.Http;
+using PostHog.FeatureManagement;
+using PostHog;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Resgrid.Web.Helpers;
+
+namespace Resgrid.Web.Middleware
+{
+ ///
+ /// Provides context and options used to evaluate feature flags for the Resgrid application.
+ ///
+ /// The used to get the current user's Id.
+ public class FeatureFlagContextProvider(IHttpContextAccessor httpContextAccessor)
+ : PostHogFeatureFlagContextProvider
+ {
+ protected override string? GetDistinctId() =>
+ httpContextAccessor.HttpContext?.User.Identity?.Name;
+
+ protected override ValueTask GetFeatureFlagOptionsAsync()
+ {
+ return ValueTask.FromResult(
+ new FeatureFlagOptions
+ {
+ PersonProperties = new Dictionary
+ {
+ ["email"] = ClaimsAuthorizationHelper.GetEmailAddress(),
+ },
+ Groups = [
+ new Group("departmentId", ClaimsAuthorizationHelper.GetDepartmentId().ToString())
+ ],
+ OnlyEvaluateLocally = true
+ });
+ }
+ }
+}
diff --git a/Web/Resgrid.Web/Program.cs b/Web/Resgrid.Web/Program.cs
index 4f296dea6..c55692c78 100644
--- a/Web/Resgrid.Web/Program.cs
+++ b/Web/Resgrid.Web/Program.cs
@@ -8,6 +8,7 @@
using Microsoft.Extensions.Logging;
using Resgrid.Config;
using Sentry.Profiling;
+using PostHog;
namespace Resgrid.Web
{
diff --git a/Web/Resgrid.Web/Resgrid.Web.csproj b/Web/Resgrid.Web/Resgrid.Web.csproj
index bab4c9e39..cfb943c75 100644
--- a/Web/Resgrid.Web/Resgrid.Web.csproj
+++ b/Web/Resgrid.Web/Resgrid.Web.csproj
@@ -57,6 +57,7 @@
+
diff --git a/Web/Resgrid.Web/Startup.cs b/Web/Resgrid.Web/Startup.cs
index 243c2593a..a203ca6f0 100644
--- a/Web/Resgrid.Web/Startup.cs
+++ b/Web/Resgrid.Web/Startup.cs
@@ -5,6 +5,7 @@
using System.Net;
using System.Net.Http;
using System.Reflection;
+using System.Reflection.PortableExecutable;
using System.Threading.Tasks;
using Audit.Core;
using Autofac;
@@ -26,6 +27,8 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
+using PostHog.Config;
+using PostHog;
using Resgrid.Config;
using Resgrid.Framework;
using Resgrid.Localization;
@@ -53,6 +56,8 @@
using StackExchange.Redis;
using Stripe;
using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;
+using Microsoft.Extensions.Http.Logging;
+using Resgrid.Web.Middleware;
namespace Resgrid.Web
{
@@ -429,6 +434,23 @@ public void ConfigureServices(IServiceCollection services)
services.AddSentryTunneling();
}
+ if (!string.IsNullOrWhiteSpace(Config.TelemetryConfig.PostHogApiKey))
+ {
+ services.AddPostHog(options =>
+ {
+ options.PostConfigure(o =>
+ {
+ o.HostUrl = new Uri(TelemetryConfig.PostHogUrl);
+ o.ProjectApiKey = TelemetryConfig.PostHogApiKey;
+ o.SuperProperties.Add("app_name", "ResgridWeb");
+ o.SuperProperties.Add("environment", SystemBehaviorConfig.Environment);
+ });
+
+ // Enables PostHog as a provider for ASP.NET Core's feature management system.
+ options.UseFeatureManagement();
+ });
+ }
+
this.Services = services;
//if (Config.ExternalErrorConfig.ApplicationInsightsEnabled)
diff --git a/Workers/Support/Quidjibo.Postgres/Quidjibo.Postgres.csproj b/Workers/Support/Quidjibo.Postgres/Quidjibo.Postgres.csproj
index c6f9f035a..559ba9bed 100644
--- a/Workers/Support/Quidjibo.Postgres/Quidjibo.Postgres.csproj
+++ b/Workers/Support/Quidjibo.Postgres/Quidjibo.Postgres.csproj
@@ -61,6 +61,7 @@
+