375 lines
13 KiB
C#
375 lines
13 KiB
C#
namespace PS.IPAM.Helpers;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Management.Automation;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using PS.IPAM;
|
|
|
|
public static class RequestHelper
|
|
{
|
|
// Handler for testing - allows injecting a mock HTTP handler
|
|
public static HttpMessageHandler? TestHttpHandler { get; set; }
|
|
|
|
public static async Task<object?> InvokeRequest(
|
|
string method,
|
|
controllers controller,
|
|
types? type = null,
|
|
subcontrollers? subController = null,
|
|
object? parameters = null,
|
|
string[]? identifiers = null,
|
|
bool ignoreSsl = false)
|
|
{
|
|
var tokenStatus = SessionManager.TestSession();
|
|
if (tokenStatus == "NoToken")
|
|
{
|
|
throw new Exception("No session available!");
|
|
}
|
|
|
|
if (tokenStatus == "Expired")
|
|
{
|
|
await UpdateSession();
|
|
}
|
|
|
|
var session = SessionManager.CurrentSession;
|
|
if (session == null)
|
|
{
|
|
throw new Exception("No session available!");
|
|
}
|
|
|
|
var uri = $"{session.URL}/api/{session.AppID}/{controller}";
|
|
if (subController != null)
|
|
{
|
|
uri += $"/{subController}";
|
|
}
|
|
if (identifiers != null && identifiers.Length > 0)
|
|
{
|
|
uri += $"/{string.Join("/", identifiers)}/";
|
|
}
|
|
|
|
using var client = SessionManager.CreateHttpClient(ignoreSsl, TestHttpHandler);
|
|
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
|
|
switch (session.AuthType)
|
|
{
|
|
case AuthType.credentials:
|
|
client.DefaultRequestHeaders.Add("token", session.Token);
|
|
break;
|
|
case AuthType.token:
|
|
client.DefaultRequestHeaders.Add("phpipam-token", session.Token);
|
|
break;
|
|
}
|
|
|
|
HttpResponseMessage? response = null;
|
|
try
|
|
{
|
|
if (method == "GET")
|
|
{
|
|
response = await client.GetAsync(uri);
|
|
}
|
|
else if (method == "POST")
|
|
{
|
|
var jsonContent = parameters != null ? JsonConvert.SerializeObject(parameters) : "{}";
|
|
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
|
|
response = await client.PostAsync(uri, content);
|
|
}
|
|
else if (method == "PATCH")
|
|
{
|
|
var jsonContent = parameters != null ? JsonConvert.SerializeObject(parameters) : "{}";
|
|
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
|
|
var request = new HttpRequestMessage(new HttpMethod("PATCH"), uri)
|
|
{
|
|
Content = content
|
|
};
|
|
response = await client.SendAsync(request);
|
|
}
|
|
else if (method == "DELETE")
|
|
{
|
|
response = await client.DeleteAsync(uri);
|
|
}
|
|
|
|
if (response == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var responseContent = await response.Content.ReadAsStringAsync();
|
|
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
|
{
|
|
return null;
|
|
}
|
|
throw new HttpRequestException($"Request failed with status {response.StatusCode}");
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(responseContent))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var jsonResponse = JsonConvert.DeserializeObject<dynamic>(responseContent);
|
|
if (jsonResponse == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (type.HasValue)
|
|
{
|
|
return ConvertToTypedObjects(jsonResponse, type.Value);
|
|
}
|
|
|
|
return jsonResponse.data;
|
|
}
|
|
catch (HttpRequestException ex)
|
|
{
|
|
if (ex.Message.Contains("404"))
|
|
{
|
|
return null;
|
|
}
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private static object? ConvertToTypedObjects(dynamic jsonResponse, types type)
|
|
{
|
|
if (jsonResponse?.data == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var data = jsonResponse.data;
|
|
if (data is JArray array)
|
|
{
|
|
return array.Select(item => ConvertSingleObject(item, type)).ToList();
|
|
}
|
|
else
|
|
{
|
|
return ConvertSingleObject(data, type);
|
|
}
|
|
}
|
|
|
|
private static object? ConvertSingleObject(dynamic item, types type)
|
|
{
|
|
var jobject = item as JObject;
|
|
if (jobject == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var customFields = new Dictionary<string, object>();
|
|
foreach (var prop in jobject.Properties())
|
|
{
|
|
if (prop.Name.StartsWith("custom_"))
|
|
{
|
|
customFields[prop.Name] = prop.Value?.ToObject<object>() ?? new object();
|
|
}
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case types.Address:
|
|
return CreateAddress(jobject, customFields);
|
|
case types.Vlan:
|
|
return CreateVlan(jobject, customFields);
|
|
case types.Subnetwork:
|
|
return CreateSubnetwork(jobject, customFields);
|
|
case types.Vrf:
|
|
return CreateVrf(jobject, customFields);
|
|
case types.Section:
|
|
return CreateSection(jobject);
|
|
case types.Tag:
|
|
return CreateTag(jobject);
|
|
case types.Nameserver:
|
|
return CreateNameserver(jobject);
|
|
case types.Domain:
|
|
return CreateDomain(jobject);
|
|
default:
|
|
return jobject.ToObject<object>();
|
|
}
|
|
}
|
|
|
|
private static Address CreateAddress(JObject jobject, Dictionary<string, object> customFields)
|
|
{
|
|
return new Address(
|
|
jobject["id"]?.ToObject<int>() ?? 0,
|
|
jobject["subnetId"]?.ToObject<int>() ?? 0,
|
|
jobject["ip"]?.ToString() ?? "",
|
|
jobject["is_gateway"]?.ToObject<bool>() ?? false,
|
|
jobject["description"]?.ToString() ?? "",
|
|
jobject["hostname"]?.ToString() ?? "",
|
|
jobject["mac"]?.ToString() ?? "",
|
|
jobject["owner"]?.ToString() ?? "",
|
|
jobject["tag"]?.ToObject<int>() ?? 0,
|
|
jobject["deviceId"]?.ToObject<int>() ?? 0,
|
|
jobject["location"]?.ToString() ?? "",
|
|
jobject["port"]?.ToString() ?? "",
|
|
jobject["note"]?.ToString() ?? "",
|
|
jobject["lastSeen"]?.ToObject<DateTime?>(),
|
|
jobject["excludePing"]?.ToObject<bool>() ?? false,
|
|
jobject["PTRignore"]?.ToObject<bool>() ?? false,
|
|
jobject["PTR"]?.ToObject<int>() ?? 0,
|
|
jobject["firewallAddressObject"]?.ToString() ?? "",
|
|
jobject["editDate"]?.ToObject<DateTime?>(),
|
|
jobject["customer_id"]?.ToObject<int>() ?? 0,
|
|
customFields.Count > 0 ? customFields : null
|
|
);
|
|
}
|
|
|
|
private static Vlan CreateVlan(JObject jobject, Dictionary<string, object> customFields)
|
|
{
|
|
return new Vlan(
|
|
jobject["vlanId"]?.ToObject<int>() ?? 0,
|
|
jobject["domainId"]?.ToObject<int>() ?? 0,
|
|
jobject["name"]?.ToString() ?? "",
|
|
jobject["number"]?.ToObject<int>() ?? 0,
|
|
jobject["description"]?.ToString() ?? "",
|
|
jobject["editDate"]?.ToObject<DateTime?>(),
|
|
jobject["customer_id"]?.ToObject<int>() ?? 0,
|
|
customFields.Count > 0 ? customFields : null
|
|
);
|
|
}
|
|
|
|
private static Subnetwork CreateSubnetwork(JObject jobject, Dictionary<string, object> customFields)
|
|
{
|
|
var props = jobject.Properties().ToList();
|
|
return new Subnetwork(
|
|
jobject["id"]?.ToObject<int>() ?? 0,
|
|
jobject["subnet"]?.ToString() ?? "",
|
|
jobject["mask"]?.ToObject<int>() ?? 0,
|
|
jobject["sectionId"]?.ToObject<int>() ?? 0,
|
|
jobject["description"]?.ToString() ?? "",
|
|
jobject["linked_subnet"]?.ToString() ?? "",
|
|
jobject["firewallAddressObject"]?.ToString() ?? "",
|
|
jobject["vrfId"]?.ToObject<int>() ?? 0,
|
|
jobject["masterSubnetId"]?.ToObject<int>() ?? 0,
|
|
jobject["allowRequests"]?.ToObject<bool>() ?? false,
|
|
jobject["vlanId"]?.ToObject<int>() ?? 0,
|
|
jobject["showName"]?.ToObject<bool>() ?? false,
|
|
jobject["deviceId"]?.ToObject<int>() ?? 0,
|
|
jobject["permissions"]?.ToString() ?? "",
|
|
jobject["pingSubnet"]?.ToObject<bool>() ?? false,
|
|
jobject["discoverSubnet"]?.ToObject<bool>() ?? false,
|
|
jobject["resolveDNS"]?.ToObject<bool>() ?? false,
|
|
jobject["DNSrecursive"]?.ToObject<bool>() ?? false,
|
|
jobject["DNSrecords"]?.ToObject<bool>() ?? false,
|
|
jobject["nameserverId"]?.ToObject<int>() ?? 0,
|
|
jobject["scanAgent"]?.ToObject<bool>() ?? false,
|
|
jobject["isFolder"]?.ToObject<bool>() ?? false,
|
|
jobject["isFull"]?.ToObject<bool>() ?? false,
|
|
jobject["isPool"]?.ToObject<bool>() ?? false,
|
|
jobject["state"]?.ToObject<int>() ?? 0,
|
|
jobject["threshold"]?.ToObject<int>() ?? 0,
|
|
jobject["location"]?.ToObject<int>() ?? 0,
|
|
jobject["editDate"]?.ToObject<DateTime?>(),
|
|
jobject["lastScan"]?.ToObject<DateTime?>(),
|
|
jobject["lastDiscovery"]?.ToObject<DateTime?>(),
|
|
jobject["calculation"]?.ToObject<object>() ?? new object(),
|
|
customFields.Count > 0 ? customFields : null
|
|
);
|
|
}
|
|
|
|
private static Vrf CreateVrf(JObject jobject, Dictionary<string, object> customFields)
|
|
{
|
|
return new Vrf(
|
|
jobject["id"]?.ToObject<int>() ?? 0,
|
|
jobject["name"]?.ToString() ?? "",
|
|
jobject["rd"]?.ToString() ?? "",
|
|
jobject["description"]?.ToString() ?? "",
|
|
jobject["sections"]?.ToString() ?? "",
|
|
jobject["editDate"]?.ToObject<DateTime?>(),
|
|
customFields.Count > 0 ? customFields : null
|
|
);
|
|
}
|
|
|
|
private static Section CreateSection(JObject jobject)
|
|
{
|
|
return new Section(
|
|
jobject["id"]?.ToObject<int>() ?? 0,
|
|
jobject["name"]?.ToString() ?? "",
|
|
jobject["description"]?.ToString() ?? "",
|
|
jobject["masterSection"]?.ToObject<int>() ?? 0,
|
|
jobject["permissions"]?.ToString() ?? "",
|
|
jobject["strictMode"]?.ToObject<bool>() ?? false,
|
|
jobject["subnetOrdering"]?.ToString() ?? "",
|
|
jobject["order"]?.ToObject<int>() ?? 0,
|
|
jobject["editDate"]?.ToObject<DateTime?>(),
|
|
jobject["showSubnet"]?.ToObject<bool>() ?? false,
|
|
jobject["showVlan"]?.ToObject<bool>() ?? false,
|
|
jobject["showVRF"]?.ToObject<bool>() ?? false,
|
|
jobject["showSupernetOnly"]?.ToObject<bool>() ?? false,
|
|
jobject["DNS"]?.ToObject<int>() ?? 0
|
|
);
|
|
}
|
|
|
|
private static Tag CreateTag(JObject jobject)
|
|
{
|
|
return new Tag(
|
|
jobject["id"]?.ToObject<int>() ?? 0,
|
|
jobject["type"]?.ToString() ?? "",
|
|
jobject["showtag"]?.ToObject<bool>() ?? false,
|
|
jobject["bgcolor"]?.ToString() ?? "",
|
|
jobject["fgcolor"]?.ToString() ?? "",
|
|
jobject["compress"]?.ToString() ?? "",
|
|
jobject["locked"]?.ToString() ?? "",
|
|
jobject["updateTag"]?.ToObject<bool>() ?? false
|
|
);
|
|
}
|
|
|
|
private static Nameserver CreateNameserver(JObject jobject)
|
|
{
|
|
return new Nameserver(
|
|
jobject["id"]?.ToObject<int>() ?? 0,
|
|
jobject["name"]?.ToString() ?? "",
|
|
jobject["nameservers"]?.ToString() ?? "",
|
|
jobject["description"]?.ToString() ?? "",
|
|
jobject["permissions"]?.ToString() ?? "",
|
|
jobject["editDate"]?.ToObject<DateTime?>()
|
|
);
|
|
}
|
|
|
|
private static Domain CreateDomain(JObject jobject)
|
|
{
|
|
return new Domain(
|
|
jobject["id"]?.ToObject<int>() ?? 0,
|
|
jobject["name"]?.ToString() ?? "",
|
|
jobject["description"]?.ToString() ?? "",
|
|
jobject["sections"]?.ToString() ?? ""
|
|
);
|
|
}
|
|
|
|
private static async Task UpdateSession()
|
|
{
|
|
var session = SessionManager.CurrentSession;
|
|
if (session == null)
|
|
{
|
|
throw new Exception("No session available!");
|
|
}
|
|
|
|
var tokenStatus = SessionManager.TestSession();
|
|
if (tokenStatus == "Valid")
|
|
{
|
|
// Just refresh the token
|
|
var result = await InvokeRequest("PATCH", controllers.user, null, null, null, null);
|
|
// Token refresh doesn't return expires in the same format, so we'll skip updating expires
|
|
return;
|
|
}
|
|
|
|
if (tokenStatus == "Expired" && session.Credentials is PSCredential creds)
|
|
{
|
|
await SessionManager.CreateSessionWithCredentials(
|
|
session.URL,
|
|
session.AppID,
|
|
creds,
|
|
false
|
|
);
|
|
}
|
|
}
|
|
}
|