namespace PS.IPAM.Helpers;
using System;
using System.Management.Automation;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
///
/// Manages phpIPAM API sessions including creation, validation, and lifecycle.
///
public static class SessionManager
{
private static Session? _currentSession;
///
/// Gets or sets the current active session.
///
public static Session? CurrentSession
{
get => _currentSession;
set => _currentSession = value;
}
///
/// Tests the current session status.
///
/// The session status indicating validity or issues.
public static SessionStatus GetSessionStatus()
{
if (_currentSession == null)
{
return SessionStatus.NoSession;
}
if (_currentSession.Expires == null)
{
return SessionStatus.Valid;
}
return _currentSession.Expires < DateTime.Now
? SessionStatus.Expired
: SessionStatus.Valid;
}
///
/// Creates a new session using username/password credentials.
///
/// The phpIPAM server URL.
/// The API application ID.
/// The PowerShell credential object.
/// Whether to ignore SSL certificate errors.
/// The created session.
public static async Task CreateSessionWithCredentialsAsync(
string url,
string appId,
PSCredential credentials,
bool ignoreSsl = false)
{
var uri = $"{url}/api/{appId}/user";
var auth = Convert.ToBase64String(
Encoding.UTF8.GetBytes($"{credentials.UserName}:{GetPasswordString(credentials)}"));
using var client = CreateHttpClient(ignoreSsl);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", auth);
var response = await client.PostAsync(uri, null);
var content = await response.Content.ReadAsStringAsync();
var jsonResponse = JsonConvert.DeserializeObject(content);
if (jsonResponse?.success != true)
{
throw new InvalidOperationException(
jsonResponse?.error?.ToString() ?? "Failed to create session");
}
var token = jsonResponse.data.token.ToString();
var expires = DateTime.Parse(jsonResponse.data.expires.ToString());
_currentSession = new Session(
AuthType.Credentials,
token,
appId,
url,
expires,
credentials
);
return _currentSession;
}
///
/// Creates a new session using a static API token.
///
/// The phpIPAM server URL.
/// The API application ID.
/// The API token.
/// The created session.
public static Session CreateSessionWithToken(string url, string appId, string token)
{
_currentSession = new Session(
AuthType.Token,
token,
appId,
url,
null,
null
);
return _currentSession;
}
///
/// Closes the current session and clears session data.
///
public static void CloseSession()
{
_currentSession = null;
}
///
/// Creates an HttpClient with optional SSL bypass.
///
/// Whether to ignore SSL certificate errors.
/// Optional custom message handler for testing.
/// A configured HttpClient instance.
public static HttpClient CreateHttpClient(bool ignoreSsl = false, HttpMessageHandler? handler = null)
{
if (handler != null)
{
return new HttpClient(handler);
}
if (ignoreSsl)
{
var sslHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (_, _, _, _) => true
};
return new HttpClient(sslHandler);
}
return new HttpClient();
}
///
/// Extracts the plain text password from a PSCredential object.
///
private static string GetPasswordString(PSCredential credential)
{
var ptr = Marshal.SecureStringToBSTR(credential.Password);
try
{
return Marshal.PtrToStringBSTR(ptr);
}
finally
{
Marshal.ZeroFreeBSTR(ptr);
}
}
}