Skip to content

Commit 01878b6

Browse files
committed
Mid-work Self-Update cleanup
1 parent 637b64c commit 01878b6

File tree

8 files changed

+196
-126
lines changed

8 files changed

+196
-126
lines changed

BLAZAM.Tests/Updates/UpdateTests.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,7 @@ private static async Task Update_Cleanup_OK(ApplicationUpdate latest)
5757
Assert.Empty(latest.UpdateStagingDirectory.Files);
5858
}
5959

60-
[Fact]
61-
public void UpdateService_HasWritePermission_ReturnsExpected()
62-
{
63-
// Should reflect the underlying credential state
64-
var hasPermission = _updateService.HasWritePermission;
65-
Assert.IsType<bool>(hasPermission);
66-
}
60+
6761

6862
[Fact]
6963
public void UpdateService_UpdateCredential_ReturnsEnum()
@@ -75,7 +69,7 @@ public void UpdateService_UpdateCredential_ReturnsEnum()
7569
[Fact]
7670
public void UpdateService_GetUpdateCredentials_ReturnsExpectedType()
7771
{
78-
var creds = _updateService.GetUpdateCredentials();
72+
var creds = _updateService.GetUpdateIdentity();
7973
// Should be null or WindowsImpersonation depending on credential
8074
Assert.True(creds == null || creds.GetType().Name == "WindowsImpersonation");
8175
}

BLAZAM/BLAZAM.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
<Nullable>enable</Nullable>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<ServerGarbageCollection>false</ServerGarbageCollection>
8-
<AssemblyVersion>1.5.2</AssemblyVersion>
9-
<Version>2026.03.12.2310</Version>
8+
<AssemblyVersion>1.5.3</AssemblyVersion>
9+
<Version>2026.03.15.2053</Version>
1010
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
1111
<RootNamespace>BLAZAM</RootNamespace>
1212
<GenerateDocumentationFile>True</GenerateDocumentationFile>

BLAZAMCommon/Data/WindowsImpersonation.cs

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,41 @@ namespace BLAZAM.Common.Data
1010
public class WindowsImpersonation
1111
{
1212
private SafeAccessTokenHandle safeAccessTokenHandle;
13-
private WindowsImpersonationUser impersonationUser;
13+
private WindowsImpersonationUser? impersonationUser;
1414
private readonly WindowsIdentity ApplicationIdentity;
1515

16-
private SafeAccessTokenHandle ImpersonatedToken
16+
private SafeAccessTokenHandle GetImpersonatedToken()
1717
{
18-
get
18+
if (impersonationUser == null)
1919
{
20-
//Use interactive logon
21-
var domain = impersonationUser.FQDN ?? "";
22-
var username = impersonationUser.Username;
23-
var phPassword = Marshal.SecureStringToGlobalAllocUnicode(impersonationUser.Password);
24-
bool returnValue = LogonUser(username,
25-
domain,
26-
phPassword,
27-
LOGON32_LOGON_BATCH,
28-
LOGON32_PROVIDER_DEFAULT,
29-
out safeAccessTokenHandle);
20+
throw new AppException("Attempted to impersonate without an impersonation user");
21+
}
22+
//Use interactive logon
23+
var domain = impersonationUser.FQDN ?? "";
24+
var username = impersonationUser.Username;
25+
var phPassword = Marshal.SecureStringToGlobalAllocUnicode(impersonationUser.Password);
26+
bool returnValue = LogonUser(username,
27+
domain,
28+
phPassword,
29+
LOGON32_LOGON_NETWORK,
30+
LOGON32_PROVIDER_DEFAULT,
31+
out safeAccessTokenHandle);
3032

3133

3234

33-
Marshal.ZeroFreeGlobalAllocUnicode(phPassword);
34-
if (false == returnValue)
35-
{
36-
int ret = Marshal.GetLastWin32Error();
37-
Loggers.ActiveDirectoryLogger.Warning("LogonUser failed with error code : {0}", ret);
38-
var exception = new System.ComponentModel.Win32Exception(ret);
39-
if (exception.NativeErrorCode == 1326)
40-
{
41-
42-
throw new AuthenticationException(exception.Message);
43-
}
44-
}
45-
return safeAccessTokenHandle;
35+
Marshal.ZeroFreeGlobalAllocUnicode(phPassword);
36+
if (!returnValue)
37+
{
38+
int ret = Marshal.GetLastWin32Error();
39+
Loggers.ActiveDirectoryLogger.Warning("LogonUser failed with error code : {0}", ret);
40+
var exception = new System.ComponentModel.Win32Exception(ret);
41+
42+
43+
throw new AuthenticationException(exception.Message);
4644

4745
}
46+
return safeAccessTokenHandle;
47+
4848
}
4949

5050
private const int LOGON32_LOGON_INTERACTIVE = 2;
@@ -70,7 +70,7 @@ private static extern bool LogonUser(string lpszUsername, string lpszDomain, Int
7070
/// Creates a new impersonation context under the provided <see cref="WindowsImpersonationUser"/>
7171
/// </summary>
7272
/// <param name="user"></param>
73-
public WindowsImpersonation(WindowsImpersonationUser user)
73+
public WindowsImpersonation(WindowsImpersonationUser? user)
7474
{
7575
impersonationUser = user;
7676
ApplicationIdentity = WindowsIdentity.GetCurrent();
@@ -81,36 +81,52 @@ public WindowsImpersonation(WindowsImpersonationUser user)
8181
/// <typeparam name="T"></typeparam>
8282
/// <param name="task"></param>
8383
/// <returns></returns>
84-
public async Task<T?> RunAsync<T>(Func<T> task) => await Task.Run(() => Run<T>(task));
84+
public async Task<T?> RunAsync<T>(Func<T> task) => await Task.Run(() => Run(task));
85+
8586
/// <summary>
86-
/// Runs the provided action synchronously as the <see cref="WindowsImpersonationUser"/>
87+
/// Runs the provided async action as the <see cref="WindowsImpersonationUser"/>
8788
/// </summary>
8889
/// <typeparam name="T"></typeparam>
8990
/// <param name="task"></param>
9091
/// <returns></returns>
91-
/// <exception cref="AppException"></exception>
92-
public T? Run<T>(Func<T> task)
93-
{
92+
public async Task<T?> RunAsync<T>(Func<Task<T>> task) =>
93+
await Task.Run(() => RunImpersonated(() => task().GetAwaiter().GetResult()));
9494

95+
/// <summary>
96+
/// Runs the provided action synchronously as the <see cref="WindowsImpersonationUser"/> or as the application identity if no user was provided
97+
/// </summary>
98+
/// <typeparam name="T"></typeparam>
99+
/// <param name="task"></param>
100+
/// <returns></returns>
101+
public T? Run<T>(Func<T> task) => RunImpersonated(() => task());
102+
103+
/// <summary>
104+
/// Core impersonation logic shared by all Run methods
105+
/// </summary>
106+
private T? RunImpersonated<T>(Func<T> executeTask)
107+
{
108+
// If no impersonation user provided, run as application identity
109+
if (impersonationUser == null)
110+
{
111+
Loggers.ActiveDirectoryLogger.Information("Running as application identity: {@Identity}", WindowsIdentity.GetCurrent().Name);
112+
return executeTask();
113+
}
95114

96115
T? result = default;
97116
try
98117
{
99-
var impersonatedToken = ImpersonatedToken;
100-
118+
var impersonatedToken = GetImpersonatedToken();
101119

102120
if (impersonatedToken == null)
103121
{
104122
throw new AppException("The impersonation user is invalid. Check settings.");
105123
}
106124

107-
108125
// Check the identity.
109-
Loggers.ActiveDirectoryLogger.Debug("Before impersonation: " + WindowsIdentity.GetCurrent().Name);
126+
Loggers.ActiveDirectoryLogger.Information("Before impersonation: {@PreIdentity}", WindowsIdentity.GetCurrent().Name);
110127

111128
try
112129
{
113-
114130
WindowsIdentity.RunImpersonated(
115131
impersonatedToken,
116132
() =>
@@ -122,13 +138,11 @@ public WindowsImpersonation(WindowsImpersonationUser user)
122138
var exception = new AppException("Impersonation running as application identity");
123139
ExceptionDispatchInfo.SetCurrentStackTrace(exception);
124140
Loggers.ActiveDirectoryLogger.Information(exception, "Impersonation running as application identity");
125-
126141
}
127-
Loggers.ActiveDirectoryLogger.Debug("During impersonation: " + WindowsIdentity.GetCurrent().Name);
128-
result = task.Invoke();
142+
Loggers.ActiveDirectoryLogger.Information("During impersonation: {@PostIdentity}", WindowsIdentity.GetCurrent().Name);
143+
result = executeTask();
129144
}
130145
);
131-
132146
}
133147
catch (IdentityNotMappedException ex)
134148
{
@@ -140,7 +154,7 @@ public WindowsImpersonation(WindowsImpersonationUser user)
140154
}
141155
finally
142156
{
143-
impersonatedToken?.Close();
157+
impersonatedToken.Close();
144158
}
145159
}
146160
catch (AuthenticationException ex)

BLAZAMCommon/GlobalSuppressions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,4 @@
5555
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:BLAZAM.Helpers.CommonHelpers.ToSidByteArray(System.String)~System.Byte[]")]
5656
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:BLAZAM.Common.Data.WindowsImpersonation.#ctor(BLAZAM.Common.Data.WindowsImpersonationUser)")]
5757
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:BLAZAM.Helpers.CommonHelpers.GetEventProperty(System.Diagnostics.Eventing.Reader.EventRecord,System.Int32)~System.String")]
58+
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:BLAZAM.Common.Data.WindowsImpersonation.RunImpersonated``1(System.Func{``0})~``0")]

BLAZAMLoggers/Loggers.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Serilog;
22
using Serilog.Events;
3+
using System.Diagnostics;
34

45
namespace BLAZAM.Logger
56
{
@@ -195,12 +196,22 @@ public static ILogger SetupLogger(string logFilePath, RollingInterval rollingInt
195196
fileSizeLimitBytes: 10000000,
196197
rollOnFileSizeLimit: true,
197198
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}",
198-
retainedFileTimeLimit: TimeSpan.FromDays(30))
199-
200-
.WriteTo.Logger(lc =>
199+
retainedFileTimeLimit: TimeSpan.FromDays(30));
200+
if (!Debugger.IsAttached)
201+
{
202+
loggerBuilder.WriteTo.Logger(lc =>
201203
{
202204
lc.Filter.ByExcluding(e => e.Level == LogEventLevel.Information).WriteTo.Console();
203205
});
206+
}
207+
else
208+
{
209+
loggerBuilder.WriteTo.Logger(lc =>
210+
{
211+
lc.WriteTo.Console();
212+
});
213+
}
214+
204215
if (SendToSeqServer)
205216
{
206217
loggerBuilder.WriteTo.Seq(SeqServerUri, apiKey: SeqAPIKey, restrictedToMinimumLevel: LogEventLevel.Warning);

BLAZAMServices/Background/AutoUpdateService.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ public AutoUpdateService(IAppDatabaseFactory factory, UpdateService updateServic
3838
_applicationInfo = applicationInfo;
3939
this.factory = factory;
4040
this.updateService = updateService;
41-
directoryCleaner = new Timer(CleanDirectories, null, TimeSpan.FromSeconds(30), TimeSpan.FromHours(20));
41+
//directoryCleaner = new Timer(CleanDirectories, null, TimeSpan.FromSeconds(30), TimeSpan.FromHours(20));
4242
}
43-
43+
/*
4444
private void CleanDirectories(object? state)
4545
{
4646
using var context = factory.CreateDbContext();
@@ -199,7 +199,7 @@ private static void TryDeleteFile(IDatabaseContext context, SystemFile file)
199199
200200
201201
}
202-
202+
*/
203203
protected override void Execute(object? state = null)
204204
{
205205
using var context = factory.CreateDbContext();

0 commit comments

Comments
 (0)