1804 lines
78 KiB
C#
1804 lines
78 KiB
C#
using C4IT.F4SDM;
|
|
using C4IT.FASD.Base;
|
|
using C4IT.Logging;
|
|
using Matrix42.Common;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Data.SqlClient;
|
|
using System.Dynamic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Web;
|
|
using update4u.SPS.DataLayer;
|
|
using update4u.SPS.DataLayer.Transaction;
|
|
using static C4IT.FASD.Base.cF4SDTicket;
|
|
using static C4IT.Logging.cLogManager;
|
|
|
|
namespace C4IT.F4SD
|
|
{
|
|
public class F4SDHelperService
|
|
{
|
|
private static Guid SPSUserClassBaseID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSUserClassBase");
|
|
private static Guid SPSAccountClassBaseID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSAccountClassBase");
|
|
private static Guid SPSCommonClassBaseID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSCommonClassBase");
|
|
private static Guid SPSAccountClassADID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSAccountClassAD");
|
|
private static Guid SPSActivityClassBaseID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSActivityClassBase");
|
|
private static Guid SPSActivityClassIncidentID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSActivityClassIncident");
|
|
private static Guid SPSActivityClassUnitOfWorkID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSActivityClassUnitOfWork");
|
|
private static Guid SPSScCategoryClassBaseID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSScCategoryClassBase");
|
|
private static Guid SPSAssetClassBaseID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSAssetClassBase");
|
|
private static Guid SPSSecurityClassRole = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSSecurityClassRole");
|
|
|
|
public static readonly Guid Administrators = new Guid("{A5D7B682-B211-4D94-A96D-8C57EEDAFDEA}");
|
|
|
|
private const string TicketCloseActionId = "51bb3283-7bd1-e511-9a82-60e327035d31";
|
|
private const string TicketDirectLinkCreateTemplate = @"{0}/wm/app-ServiceDesk/notSet/create-object/{1}?view-options=%7B%22embedded%22:false%7D&presetParams={2}";
|
|
private const string IncidentDirectLinkCloseTemplate = @"{0}/wm/app-ServiceDesk/notSet/preview-object/SPSActivityTypeIncident/{1}/0/?view-options={2}";
|
|
private const string TicketDirectLinkPreviewTemplate = @"{0}/wm/app-ServiceDesk/notSet/preview-object/{1}/{2}/0/";
|
|
private const string TicketDirectLinkEditTemplate = @"{0}/wm/app-ServiceDesk/notSet/edit-object/{1}/{2}";
|
|
|
|
private const string placeHolderSubject = "PARAM_SUBJECT";
|
|
private const string placeHolderDescription = "PARAM_DESCRIPTION";
|
|
private const string c4itf4sdmonLinkBase = "f4sdsend://localhost";
|
|
|
|
private const string F4SDTicketTableName = "M42WPM-TICKETS-INFOS";
|
|
private const string F4SDTicketStatusColumnName = "STATUS";
|
|
|
|
|
|
public static IEnumerable<string> ReadLines(Func<Stream> streamProvider,
|
|
Encoding encoding)
|
|
{
|
|
using (var stream = streamProvider())
|
|
using (var reader = new StreamReader(stream, encoding))
|
|
{
|
|
string line;
|
|
while ((line = reader.ReadLine()) != null)
|
|
{
|
|
yield return line;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal async Task<string> getDirectLinkF4SD(Guid EOID, string type)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
LogEntry($"Generating F4SD URI for type: '{type}', GUID: '{EOID}'", LogLevels.Debug);
|
|
var builder = new UriBuilder(c4itf4sdmonLinkBase);
|
|
var queryString = HttpUtility.ParseQueryString(builder.Query);
|
|
|
|
switch (type.ToLowerInvariant().Split('.').Last())
|
|
{
|
|
case "person":
|
|
case "user":
|
|
var user = getUsersByAsql($"[Expression-ObjectId]='{EOID}'")?.FirstOrDefault();
|
|
string Sids = string.Empty;
|
|
|
|
if (user != null)
|
|
{
|
|
var accounts = getAccountsByAsql($"Owner='{user.Id}'");
|
|
Sids = string.Join(",", accounts?.Where(x => !string.IsNullOrEmpty(x.Sid)).Select(x => x.Sid) ?? Array.Empty<string>());
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(user?.Name))
|
|
{
|
|
queryString.Add("command", "UserSidSearch");
|
|
queryString.Add("name", user.Name);
|
|
queryString.Add("sids", Sids);
|
|
}
|
|
break;
|
|
|
|
case "asset":
|
|
var asset = getAssetsByAsql($"UsedInTypeSPSComputerType is not null AND [Expression-ObjectId]='{EOID}'")?.FirstOrDefault();
|
|
if (asset != null)
|
|
{
|
|
queryString.Add("command", "ComputerDomainSearch");
|
|
queryString.Add("name", asset.Name);
|
|
queryString.Add("domain", asset.DomainName);
|
|
}
|
|
break;
|
|
|
|
case "incident":
|
|
case "servicerequest":
|
|
case "ticket":
|
|
var ticket = (await getTicketDetails(new List<Guid> { EOID }))?.FirstOrDefault();
|
|
if (ticket != null)
|
|
{
|
|
queryString.Add("command", "TicketSearch");
|
|
queryString.Add("tname", ticket.Name);
|
|
queryString.Add("tid", ticket.TicketObjectId.ToString());
|
|
|
|
if (ticket.AffectedUserId != Guid.Empty)
|
|
{
|
|
var initiator = getUsersByAsql($"ID = '{ticket.AffectedUserId}'")?.FirstOrDefault();
|
|
string userName = initiator?.Name;
|
|
Sids = string.Join(",", getAccountsByAsql($"Owner='{ticket.AffectedUserId}'")?.Where(x => !string.IsNullOrEmpty(x.Sid)).Select(x => x.Sid) ?? Array.Empty<string>());
|
|
|
|
queryString.Add("uname", userName);
|
|
queryString.Add("sids", Sids);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
builder.Query = queryString.ToString();
|
|
return string.IsNullOrEmpty(builder.Query) ? null : builder.ToString();
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
|
|
internal async Task<List<cF4SDTicketSummary>> getTicketListByUser(string userSid, int hours, int queueoption, List<cApiM42TicketQueueInfo> queues)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
LogEntry($"Generating ticket list for userSid: '{userSid}', {hours} hours", LogLevels.Debug);
|
|
await Task.Delay(0);
|
|
|
|
var tickets = new List<cF4SDTicketSummary>();
|
|
var activityFilter = GetActivityFilter(userSid, hours, ticketAndServiceRequestEnabled(), queueoption, queues);
|
|
LogEntry($"ASql Filter: {activityFilter}");
|
|
|
|
var activityTable = FragmentRequestBase.SimpleLoad(SPSActivityClassBaseID,
|
|
string.Format("[Expression-ObjectID] as EOID, TicketNumber, Subject, Service.ID as ServiceId, Service.Name as ServiceName, SUBQUERY(BasicSchemaObjectType as bso, bso.Name, bso.id = base.T(SPSCommonClassBase).TypeID) as ActivityType" +
|
|
", COALESCE(T(SPSActivityClassIncident).Asset.T(SPSComputerClassBase).Name, T(SPSActivityClassIncident).Asset.T(SPSAssetClassSIMCard).PhoneNumber, T(SPSActivityClassIncident).Asset.Name, T(SPSActivityClassIncident).Asset.objectid) as AssetName" +
|
|
", SUBQUERY(BasicSchemaObjectType AS t, t.Name, t.ID=base.T(SPSActivityClassIncident).Asset.T(SPSCommonClassBase).TypeID) as AssetCIName" +
|
|
", CASE WHEN Initiator.PrimaryAccount.T(SPSAccountClassAd).Sid = '{0}' THEN 1 ELSE 0 END AS IsPrimaryAccount",
|
|
userSid),
|
|
activityFilter);
|
|
|
|
if (activityTable?.Rows == null || activityTable.Rows.Count == 0)
|
|
{
|
|
LogEntry($"No activity entries found for userSid: '{userSid}'", LogLevels.Warning);
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < activityTable.Rows.Count; i++)
|
|
{
|
|
DataRow entry = activityTable.Rows[i];
|
|
var activityEOId = getGuidFromObject(entry["EOID"]);
|
|
var ticketNumber = getStringFromObject(entry["TicketNumber"]);
|
|
var activityType = getStringFromObject(entry["ActivityType"]);
|
|
var assetName = getStringFromObject(entry["AssetName"]);
|
|
var ServiceName = getStringFromObject(entry["ServiceName"]);
|
|
var assetCIName = getStringFromObject(entry["AssetCIName"]);
|
|
var subject = getStringFromObject(entry["Subject"]);
|
|
|
|
var stateData = GetActivityState(activityEOId);
|
|
var state = stateData.Item1;
|
|
var stateDisp = stateData.Item2;
|
|
|
|
LogEntry($"Activity found {i + 1}/{activityTable.Rows.Count}: ObjectID={activityEOId}, TicketNumber={ticketNumber}, Subject={subject}, State={state}", LogLevels.Debug);
|
|
|
|
if (string.IsNullOrEmpty(ticketNumber))
|
|
{
|
|
LogEntry($"No TicketNumber found for activity entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(assetName))
|
|
{
|
|
LogEntry($"No AssetName found for activity entry", LogLevels.Debug);
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(assetCIName))
|
|
{
|
|
LogEntry($"No AssetCIName found for activity entry", LogLevels.Debug);
|
|
}
|
|
var ServiceId = getGuidFromObject(entry["ServiceId"]);
|
|
if (ServiceId == Guid.Empty)
|
|
{
|
|
LogEntry($"no ServiceId found for activity entry", LogLevels.Debug);
|
|
}
|
|
var AssetCIName = getStringFromObject(entry["AssetCIName"]);
|
|
if (AssetCIName == string.Empty)
|
|
{
|
|
LogEntry($"no AssetCIName found for activity entry", LogLevels.Debug);
|
|
}
|
|
var Subject = getStringFromObject(entry["Subject"]);
|
|
if (Subject == string.Empty)
|
|
{
|
|
LogEntry($"no Subject found for activity entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
var IsPrimaryAccount = getIntFromObject(entry["IsPrimaryAccount"]);
|
|
|
|
if (string.IsNullOrEmpty(subject))
|
|
{
|
|
LogEntry($"No Subject found for activity entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
tickets.Add(new cF4SDTicketSummary()
|
|
{
|
|
TicketObjectId = activityEOId,
|
|
Name = ticketNumber,
|
|
ActivityType = activityType,
|
|
AssetCIName = assetCIName,
|
|
AssetName = assetName,
|
|
ServiceId = ServiceId,
|
|
ServiceName = ServiceName,
|
|
StatusId = state,
|
|
Status = stateDisp,
|
|
Summary = subject,
|
|
IsPrimaryAccount = IsPrimaryAccount == 1
|
|
});
|
|
}
|
|
|
|
tickets = tickets.OrderByDescending(x => x.Name).ToList();
|
|
return tickets;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
private static readonly string[] TicketOverviewKeys = new[]
|
|
{
|
|
"TicketsNew",
|
|
"TicketsActive",
|
|
"TicketsCritical",
|
|
"TicketsNewInfo",
|
|
"IncidentNew",
|
|
"IncidentActive",
|
|
"IncidentCritical",
|
|
"IncidentNewInfo",
|
|
"UnassignedTickets",
|
|
"UnassignedTicketsCritical"
|
|
};
|
|
|
|
public class TicketOverviewCountsResult
|
|
{
|
|
[JsonProperty("counts")]
|
|
public Dictionary<string, int> Counts { get; set; } = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
|
}
|
|
|
|
public class TicketOverviewRelationDto
|
|
{
|
|
public enumF4sdSearchResultClass Type { get; set; }
|
|
public string Name { get; set; }
|
|
public string DisplayName { get; set; }
|
|
public Guid id { get; set; }
|
|
public enumF4sdSearchResultStatus Status { get; set; } = enumF4sdSearchResultStatus.Unknown;
|
|
public Dictionary<string, string> Infos { get; set; } = null;
|
|
public List<cF4sdIdentityEntry> Identities { get; set; } = null;
|
|
}
|
|
|
|
private sealed class TicketOverviewEntry
|
|
{
|
|
public Guid TicketId { get; set; }
|
|
public string TicketNumber { get; set; }
|
|
public string Summary { get; set; }
|
|
public Guid InitiatorId { get; set; }
|
|
public string InitiatorDisplayName { get; set; }
|
|
public string InitiatorAccount { get; set; }
|
|
public string InitiatorDomain { get; set; }
|
|
public Guid RecipientId { get; set; }
|
|
public Guid RecipientRoleId { get; set; }
|
|
public int State { get; set; }
|
|
public DateTime CreatedDate { get; set; }
|
|
public bool NewInformationReceived { get; set; }
|
|
public bool ReactionTimeEscalated { get; set; }
|
|
public bool SolutionTimeEscalated { get; set; }
|
|
public bool IsIncident { get; set; }
|
|
}
|
|
|
|
internal async Task<TicketOverviewCountsResult> getTicketOverviewCounts(string sid, string scope, IEnumerable<string> keys)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
var useRoleScope = string.Equals(scope, "role", StringComparison.OrdinalIgnoreCase);
|
|
var normalizedKeys = (keys ?? Array.Empty<string>())
|
|
.Where(k => !string.IsNullOrWhiteSpace(k))
|
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
.ToList();
|
|
|
|
if (normalizedKeys.Count == 0)
|
|
{
|
|
normalizedKeys.AddRange(TicketOverviewKeys);
|
|
}
|
|
|
|
var entries = await LoadTicketOverviewEntries(sid, useRoleScope);
|
|
var counts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
|
|
|
foreach (var key in normalizedKeys)
|
|
{
|
|
counts[key] = entries.Count(entry => MatchesTicketOverviewKey(entry, key));
|
|
}
|
|
|
|
return new TicketOverviewCountsResult { Counts = counts };
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return new TicketOverviewCountsResult();
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
internal async Task<List<TicketOverviewRelationDto>> getTicketOverviewRelations(string sid, string scope, string key, int count)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
if (string.IsNullOrWhiteSpace(key))
|
|
return new List<TicketOverviewRelationDto>();
|
|
|
|
var useRoleScope = string.Equals(scope, "role", StringComparison.OrdinalIgnoreCase);
|
|
var entries = await LoadTicketOverviewEntries(sid, useRoleScope);
|
|
|
|
var filtered = entries
|
|
.Where(entry => MatchesTicketOverviewKey(entry, key))
|
|
.OrderByDescending(entry => entry.CreatedDate)
|
|
.ToList();
|
|
|
|
if (count > 0)
|
|
filtered = filtered.Take(count).ToList();
|
|
|
|
var relations = new List<TicketOverviewRelationDto>(filtered.Count);
|
|
foreach (var entry in filtered)
|
|
{
|
|
var relation = new TicketOverviewRelationDto
|
|
{
|
|
Type = enumF4sdSearchResultClass.Ticket,
|
|
DisplayName = entry.TicketNumber ?? string.Empty,
|
|
Name = entry.TicketNumber ?? string.Empty,
|
|
id = entry.TicketId,
|
|
Status = enumF4sdSearchResultStatus.Active,
|
|
Infos = new Dictionary<string, string>
|
|
{
|
|
["Summary"] = entry.Summary ?? string.Empty,
|
|
["StatusId"] = ConvertM42State(entry.State),
|
|
["UserDisplayName"] = entry.InitiatorDisplayName ?? string.Empty,
|
|
["UserAccount"] = entry.InitiatorAccount ?? string.Empty,
|
|
["UserDomain"] = entry.InitiatorDomain ?? string.Empty
|
|
},
|
|
Identities = new List<cF4sdIdentityEntry>
|
|
{
|
|
new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = entry.TicketId },
|
|
new cF4sdIdentityEntry { Class = enumFasdInformationClass.User, Id = entry.InitiatorId }
|
|
}
|
|
};
|
|
relations.Add(relation);
|
|
}
|
|
|
|
return relations;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return new List<TicketOverviewRelationDto>();
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
private async Task<List<TicketOverviewEntry>> LoadTicketOverviewEntries(string sid, bool useRoleScope)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
await Task.Delay(0);
|
|
|
|
if (string.IsNullOrWhiteSpace(sid))
|
|
return new List<TicketOverviewEntry>();
|
|
|
|
var filter = await BuildTicketOverviewFilterAsync(sid, useRoleScope);
|
|
if (string.IsNullOrWhiteSpace(filter))
|
|
return new List<TicketOverviewEntry>();
|
|
|
|
var tbl = FragmentRequestBase.SimpleLoad(SPSActivityClassBaseID,
|
|
"[Expression-ObjectID] as EOID" +
|
|
", TicketNumber" +
|
|
", Subject" +
|
|
", Initiator as InitiatorId" +
|
|
", Initiator.LastName + ISNULL(', ' + Initiator.FirstName, '') as Initiator" +
|
|
", Initiator.PrimaryAccount.T(SPSAccountClassAD).NBAccountName as InitiatorAccount" +
|
|
", Initiator.PrimaryAccount.T(SPSAccountClassAD).Domain.NT4Name as InitiatorDomain" +
|
|
", Recipient as RecipientId" +
|
|
", RecipientRole as RecipientRoleId" +
|
|
", T(SPSCommonClassBase).State as State" +
|
|
", CreatedDate" +
|
|
", NewInformationReceived" +
|
|
", ReactionTimeEscalated" +
|
|
", SolutionTimeEscalated" +
|
|
", UsedInTypeSPSActivityTypeIncident as IsIncident",
|
|
filter);
|
|
|
|
if (tbl?.Rows == null || tbl.Rows.Count == 0)
|
|
return new List<TicketOverviewEntry>();
|
|
|
|
var entries = new List<TicketOverviewEntry>(tbl.Rows.Count);
|
|
foreach (DataRow row in tbl.Rows)
|
|
{
|
|
var ticketId = getGuidFromObject(row["EOID"]);
|
|
if (ticketId == Guid.Empty)
|
|
continue;
|
|
|
|
entries.Add(new TicketOverviewEntry
|
|
{
|
|
TicketId = ticketId,
|
|
TicketNumber = getStringFromObject(row["TicketNumber"]),
|
|
Summary = getStringFromObject(row["Subject"]),
|
|
InitiatorId = getGuidFromObject(row["InitiatorId"]),
|
|
InitiatorDisplayName = getStringFromObject(row["Initiator"]),
|
|
InitiatorAccount = getStringFromObject(row["InitiatorAccount"]),
|
|
InitiatorDomain = getStringFromObject(row["InitiatorDomain"]),
|
|
RecipientId = getGuidFromObject(row["RecipientId"]),
|
|
RecipientRoleId = getGuidFromObject(row["RecipientRoleId"]),
|
|
State = getIntFromObject(row["State"]),
|
|
CreatedDate = getDateTimeFromObject(row["CreatedDate"]),
|
|
NewInformationReceived = GetBoolValue(row["NewInformationReceived"]),
|
|
ReactionTimeEscalated = GetBoolValue(row["ReactionTimeEscalated"]),
|
|
SolutionTimeEscalated = GetBoolValue(row["SolutionTimeEscalated"]),
|
|
IsIncident = row["IsIncident"] != DBNull.Value
|
|
});
|
|
}
|
|
|
|
return entries;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return new List<TicketOverviewEntry>();
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
private async Task<string> BuildTicketOverviewFilterAsync(string sid, bool useRoleScope)
|
|
{
|
|
var filter = "T(SPSCommonClassBase).State <> 204";
|
|
|
|
if (ticketAndServiceRequestEnabled())
|
|
{
|
|
filter += " AND (UsedInTypeSPSActivityTypeIncident IS NOT NULL" +
|
|
" OR UsedInTypeSPSActivityTypeTicket IS NOT NULL" +
|
|
" OR UsedInTypeSPSActivityTypeServiceRequest IS NOT NULL)";
|
|
}
|
|
else
|
|
{
|
|
filter += " AND (UsedInTypeSPSActivityTypeIncident IS NOT NULL)";
|
|
}
|
|
|
|
if (!useRoleScope)
|
|
{
|
|
filter += $" AND Initiator.Accounts.T(SPSAccountClassAd).Sid = '{Escape(sid)}'";
|
|
return filter;
|
|
}
|
|
|
|
var userId = getUserBySid(sid);
|
|
if (userId == Guid.Empty)
|
|
return null;
|
|
|
|
var roles = await getRoleMembershipById(userId) ?? new List<M42Role>();
|
|
if (roles.Count == 0)
|
|
return null;
|
|
|
|
var roleIDs = roles
|
|
.Select(role => role?.Id)
|
|
.Where(Id => !Guid.Empty.Equals(Id))
|
|
.Select(Id => $"'{(Id)}'")
|
|
.ToList();
|
|
|
|
if (roleIDs.Count == 0)
|
|
return null;
|
|
|
|
filter += $" AND RecipientRole.T(SPSSecurityClassRole).ID IN ({string.Join(", ", roleIDs)})";
|
|
return filter;
|
|
}
|
|
|
|
private static bool MatchesTicketOverviewKey(TicketOverviewEntry entry, string key)
|
|
{
|
|
if (entry == null || string.IsNullOrWhiteSpace(key))
|
|
return false;
|
|
|
|
var isTicket = !entry.IsIncident;
|
|
var isAssigned = entry.RecipientId != Guid.Empty || entry.RecipientRoleId != Guid.Empty;
|
|
var isCritical = entry.ReactionTimeEscalated || entry.SolutionTimeEscalated;
|
|
var isNew = entry.State == 200;
|
|
var isActive = entry.State == 201 || entry.State == 202 || entry.State == 203;
|
|
|
|
switch (key.Trim())
|
|
{
|
|
case "TicketsNew":
|
|
return isTicket && isAssigned && isNew;
|
|
case "TicketsActive":
|
|
return isTicket && isAssigned && isActive;
|
|
case "TicketsCritical":
|
|
return isTicket && isAssigned && isCritical;
|
|
case "TicketsNewInfo":
|
|
return isTicket && isAssigned && entry.NewInformationReceived;
|
|
case "IncidentNew":
|
|
return entry.IsIncident && isNew;
|
|
case "IncidentActive":
|
|
return entry.IsIncident && isActive;
|
|
case "IncidentCritical":
|
|
return entry.IsIncident && isCritical;
|
|
case "IncidentNewInfo":
|
|
return entry.IsIncident && entry.NewInformationReceived;
|
|
case "UnassignedTickets":
|
|
return isTicket && !isAssigned && isNew;
|
|
case "UnassignedTicketsCritical":
|
|
return isTicket && !isAssigned && isCritical;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static bool GetBoolValue(object value)
|
|
{
|
|
if (value == null || value is DBNull)
|
|
return false;
|
|
if (value is bool boolValue)
|
|
return boolValue;
|
|
if (value is int intValue)
|
|
return intValue != 0;
|
|
if (value is long longValue)
|
|
return longValue != 0;
|
|
|
|
if (bool.TryParse(value.ToString(), out var parsedBool))
|
|
return parsedBool;
|
|
if (int.TryParse(value.ToString(), out var parsedInt))
|
|
return parsedInt != 0;
|
|
|
|
return false;
|
|
}
|
|
|
|
private static string ConvertM42State(int state)
|
|
{
|
|
switch (state)
|
|
{
|
|
case 200:
|
|
return "New";
|
|
case 201:
|
|
case 202:
|
|
return "InProgress";
|
|
case 203:
|
|
return "OnHold";
|
|
case 204:
|
|
return "Closed";
|
|
default:
|
|
return "Unknown";
|
|
}
|
|
}
|
|
private (int, string) GetActivityState(Guid activityEOId)
|
|
{
|
|
var tbl3 = FragmentRequestBase.SimpleLoad(SPSCommonClassBaseID,
|
|
"State.Value as State, State.DisplayString as StateDisp", $"[Expression-ObjectID] = '{activityEOId}'");
|
|
if (tbl3?.Rows == null || tbl3.Rows.Count <= 0)
|
|
{
|
|
LogEntry($"SPSCommonClassBase fragment not found: ClassId={SPSCommonClassBaseID}, ObjectId={activityEOId}", LogLevels.Debug);
|
|
return (0, "");
|
|
}
|
|
var state = getIntFromObject(tbl3.Rows[0]["State"]);
|
|
var stateDisp = getStringFromObject(tbl3.Rows[0]["StateDisp"]);
|
|
return (state, stateDisp);
|
|
}
|
|
private string Escape(string input)
|
|
{
|
|
return input?.Replace("'", "''");
|
|
}
|
|
private string GetActivityFilter(
|
|
string userSid,
|
|
int hours,
|
|
bool ticketAndServiceRequestEnabled,
|
|
int queueoption,
|
|
List<cApiM42TicketQueueInfo> queues
|
|
)
|
|
{
|
|
// Baseline-Filter auf User und Datum
|
|
var filter = $"Initiator.Accounts.T(SPSAccountClassAd).Sid = '{Escape(userSid)}'";
|
|
|
|
string fStartDate = AsqlHelper.PrepareDateTime(DateTime.UtcNow.AddHours(-hours), true);
|
|
string fEndDate = AsqlHelper.PrepareDateTime(DateTime.UtcNow, true);
|
|
|
|
// Incident vs. Ticket/ServiceRequest
|
|
if (ticketAndServiceRequestEnabled)
|
|
{
|
|
filter +=
|
|
" AND (UsedInTypeSPSActivityTypeIncident IS NOT NULL" +
|
|
" OR UsedInTypeSPSActivityTypeTicket IS NOT NULL" +
|
|
" OR UsedInTypeSPSActivityTypeServiceRequest IS NOT NULL)";
|
|
}
|
|
else
|
|
{
|
|
filter += " AND (UsedInTypeSPSActivityTypeIncident IS NOT NULL)";
|
|
}
|
|
|
|
// Offene bzw. kürzlich geschlossene Objekte
|
|
filter +=
|
|
" AND (T(SPSCommonClassBase).State <> 204" +
|
|
$" OR (ClosedDate > {fStartDate} AND ClosedDate < {fEndDate}))";
|
|
|
|
// Queue-Filter nur, wenn tatsächlich Queues übergeben wurden
|
|
if (queues != null && queues.Count > 0)
|
|
{
|
|
// URL-escaping für Name und ID
|
|
var escapedNames = queues
|
|
.Select(q => $"'{Escape(q.QueueName)}'")
|
|
.ToList();
|
|
var escapedIds = queues
|
|
.Select(q => $"'{Escape(q.QueueID.ToString())}'")
|
|
.ToList();
|
|
|
|
string nameList = string.Join(", ", escapedNames);
|
|
string idList = string.Join(", ", escapedIds);
|
|
|
|
switch (queueoption)
|
|
{
|
|
// 1 = entweder keine Queue oder eine der übergebenen Queues (Name oder ID)
|
|
case 1:
|
|
filter +=
|
|
$" AND (" +
|
|
"Queue IS NULL" +
|
|
$" OR Queue.Name IN ({nameList})" +
|
|
$" OR Queue.ID IN ({idList})" +
|
|
")";
|
|
break;
|
|
|
|
// 2 = nur die übergebenen Queues (Name oder ID)
|
|
case 2:
|
|
filter +=
|
|
$" AND (" +
|
|
"Queue IS NOT NULL" +
|
|
$" AND (Queue.Name IN ({nameList})" +
|
|
$" OR Queue.ID IN ({idList}))" +
|
|
")";
|
|
break;
|
|
|
|
// 3 = nur Objekte ohne Queue
|
|
case 3:
|
|
filter += " AND Queue IS NULL";
|
|
break;
|
|
|
|
// 0 oder andere = keine zusätzliche Einschränkung
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (queueoption == 3)
|
|
{
|
|
// Ausnahme: wenn keine Queues übergeben, aber Option 3 = nur ohne Queue
|
|
filter += " AND Queue IS NULL";
|
|
}
|
|
|
|
return filter;
|
|
}
|
|
|
|
|
|
internal async Task<DirectLink> getDirectLinkCreateTicket(string sid, string assetname)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
await Task.Delay(0);
|
|
|
|
// get global settings
|
|
bool TicketAndServiceRequestEnabled = ticketAndServiceRequestEnabled();
|
|
|
|
var user = getUserBySid(sid);
|
|
var asset = getAssetByName(assetname);
|
|
dynamic presetParamsDyn = new ExpandoObject();
|
|
|
|
presetParamsDyn.SPSActivityClassBase = new ExpandoObject();
|
|
presetParamsDyn.SPSActivityClassBase.Subject = placeHolderSubject;
|
|
presetParamsDyn.SPSActivityClassBase.DescriptionHTML = placeHolderDescription;
|
|
if (user != Guid.Empty)
|
|
presetParamsDyn.SPSActivityClassBase.Initiator = user;
|
|
if (asset != null)
|
|
{
|
|
presetParamsDyn.SPSActivityClassIncident = new ExpandoObject();
|
|
presetParamsDyn.SPSActivityClassIncident.Asset = asset.Id;
|
|
}
|
|
var type = TicketAndServiceRequestEnabled ? "SPSActivityTypeTicket" : "SPSActivityTypeIncident";
|
|
var presetParams = HttpUtility.UrlEncode(JsonConvert.SerializeObject(presetParamsDyn));
|
|
var directLink = string.Format(TicketDirectLinkCreateTemplate, F4SDM42WebApiController.defaultInstance.BaseUrl, type, presetParams);
|
|
return new DirectLink()
|
|
{
|
|
Link = directLink,
|
|
DescriptionParameter = placeHolderDescription,
|
|
SubjectParameter = placeHolderSubject
|
|
};
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
private static bool ticketAndServiceRequestEnabled()
|
|
{
|
|
var configProvider = F4SDM42WebApiController.defaultInstance._globalConfigurationProvider;
|
|
|
|
// using reflection because signature of "ReloadSettings" changed in ESM v12
|
|
var method = configProvider.GetType().GetMethod("ReloadSettings");
|
|
|
|
if (method != null)
|
|
{
|
|
var defaultParameters = method.GetParameters().Select(p => p.HasDefaultValue ? p.DefaultValue : null).ToArray();
|
|
method.Invoke(configProvider, defaultParameters);
|
|
}
|
|
|
|
return configProvider.ServiceDeskConfiguration.TicketAndServiceRequestEnabled;
|
|
}
|
|
|
|
internal async Task<List<cF4SDTicket>> getTicketDetails(List<Guid> ticketObjectIds)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
await Task.Delay(0);
|
|
|
|
var Filter = AsqlHelper.BuildInCondition("[Expression-ObjectId]", ticketObjectIds);
|
|
LogEntry($"ASql Filter: {Filter}");
|
|
|
|
var tbl = FragmentRequestBase.SimpleLoad(SPSActivityClassBaseID,
|
|
"[Expression-ObjectId] as EOID" +
|
|
", TicketNumber" +
|
|
", Subject" +
|
|
", Category.Name as Category" +
|
|
", Category as CategoryId" +
|
|
", CreatedDate, ClosedDate" +
|
|
", Initiator as InitiatorId" +
|
|
", Initiator.LastName + ISNULL(', ' + Initiator.FirstName, '') as Initiator" +
|
|
", DescriptionHTML" +
|
|
", Impact" +
|
|
", Impact.DisplayString as ImpactDisp" +
|
|
", Urgency" +
|
|
", Urgency.DisplayString as UrgencyDisp" +
|
|
", Priority" +
|
|
", Priority.Description as PrioDisp" +
|
|
", SolutionHTML", Filter);
|
|
|
|
if (tbl == null || tbl.Rows == null)
|
|
{
|
|
LogEntry($"No activity entry list found with [Expression-ObjectId]='{string.Join(", ", ticketObjectIds)}'", LogLevels.Warning);
|
|
return null;
|
|
}
|
|
|
|
var tickets = new List<cF4SDTicket>();
|
|
|
|
foreach (DataRow Entry in tbl.Rows)
|
|
{
|
|
var ActivityEOID = getGuidFromObject(Entry["EOID"]);
|
|
if (ActivityEOID == Guid.Empty)
|
|
{
|
|
LogEntry($"No expression object id found for activity entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
var InitiatorId = getGuidFromObject(Entry["InitiatorId"]);
|
|
var Initiator = getStringFromObject(Entry["Initiator"]);
|
|
if (InitiatorId == Guid.Empty)
|
|
{
|
|
LogEntry($"No Initiator id found for activity entry", LogLevels.Warning);
|
|
}
|
|
|
|
var TicketNumber = getStringFromObject(Entry["TicketNumber"]);
|
|
if (string.IsNullOrEmpty(TicketNumber))
|
|
{
|
|
LogEntry($"No TicketNumber found for activity entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
var CategoryId = getGuidFromObject(Entry["CategoryId"]);
|
|
if (CategoryId == Guid.Empty)
|
|
{
|
|
LogEntry($"No Initiator object id found for activity entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
var Category = getStringFromObject(Entry["Category"]);
|
|
if (string.IsNullOrEmpty(Category))
|
|
{
|
|
LogEntry($"No Category found for activity entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
var CreatedDate = getDateTimeFromObject(Entry["CreatedDate"]);
|
|
if (CreatedDate == DateTime.MinValue)
|
|
{
|
|
LogEntry($"No CreationDate found for activity entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
var ClosedDate = getDateTimeFromObject(Entry["ClosedDate"]);
|
|
var DescriptionHtml = getStringFromObject(Entry["DescriptionHTML"]);
|
|
var Description = DescriptionHtml != string.Empty ? Matrix42.Common.Html.HtmlConverter.ConvertHtmlToPlainText(DescriptionHtml) : string.Empty;
|
|
|
|
var SolutionHtml = getStringFromObject(Entry["SolutionHTML"]);
|
|
var Solution = SolutionHtml != string.Empty ? Matrix42.Common.Html.HtmlConverter.ConvertHtmlToPlainText(SolutionHtml) : string.Empty;
|
|
|
|
var Subject = getStringFromObject(Entry["Subject"]);
|
|
if (string.IsNullOrEmpty(Subject))
|
|
{
|
|
LogEntry($"No Subject found for activity entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
var PriorityId = getIntFromObject(Entry["Priority"]);
|
|
var Priority = getStringFromObject(Entry["PrioDisp"]);
|
|
|
|
var UrgencyId = getIntFromObject(Entry["Urgency"]);
|
|
var Urgency = getStringFromObject(Entry["UrgencyDisp"]);
|
|
|
|
var ImpactId = getIntFromObject(Entry["Impact"]);
|
|
var Impact = getStringFromObject(Entry["ImpactDisp"]);
|
|
|
|
LogEntry($"get category information: {Filter}");
|
|
Filter = string.Format("Recursive(Children).T(SPSScCategoryClassBase).Id='{0}'", CategoryId);
|
|
var tbl1 = FragmentRequestBase.SimpleLoad(SPSScCategoryClassBaseID, "Name", Filter);
|
|
if (tbl1?.Rows == null || tbl1.Rows.Count <= 0)
|
|
{
|
|
LogEntry($"No Category entry list found with Initiator='{CategoryId}'", LogLevels.Warning);
|
|
return null;
|
|
}
|
|
|
|
var CategoryHierarchical = string.Join(" > ", tbl1.Rows.Cast<DataRow>().Reverse().Select(row => getStringFromObject(row["Name"])));
|
|
|
|
var tbl2 = FragmentRequestBase.SimpleLoad(SPSActivityClassIncidentID, "EntryBy as EntryBy, EntryBy.DisplayString as EntryByDisp, COALESCE(AssetAffected, Asset) as Asset, COALESCE(AssetAffected.T(SPSComputerClassAD).Domain.NT4Name, Asset.T(SPSComputerClassAD).Domain.NT4Name) as AssetDomain, COALESCE(COALESCE(AssetAffected.T(SPSComputerClassBase).Name, AssetAffected.T(SPSAssetClassSIMCard).PhoneNumber, AssetAffected.Name, AssetAffected.objectid), COALESCE(Asset.T(SPSComputerClassBase).Name, Asset.T(SPSAssetClassSIMCard).PhoneNumber, Asset.Name, Asset.objectid)) as AssetName", $"[Expression-ObjectID] = '{ActivityEOID}'");
|
|
|
|
if (tbl2?.Rows == null || tbl2.Rows.Count <= 0)
|
|
{
|
|
LogEntry($"SPSActivityClassIncident fragment not found: ClassId={SPSActivityClassIncidentID}, ObjectId={ActivityEOID}", LogLevels.Debug);
|
|
continue;
|
|
}
|
|
|
|
var AssetId = getGuidFromObject(tbl2.Rows[0]["Asset"]);
|
|
var Asset = getStringFromObject(tbl2.Rows[0]["AssetName"]);
|
|
var AssetDomain = getStringFromObject(tbl2.Rows[0]["AssetDomain"]);
|
|
var EntryBy = getIntFromObject(tbl2.Rows[0]["EntryBy"]);
|
|
var EntryByDisp = getStringFromObject(tbl2.Rows[0]["EntryByDisp"]);
|
|
|
|
M42Asset AssetObject = null;
|
|
if (AssetId != Guid.Empty)
|
|
AssetObject = getAssetsByAsql($"ID = '{AssetId}'").FirstOrDefault();
|
|
|
|
var tbl3 = FragmentRequestBase.SimpleLoad(SPSCommonClassBaseID, "State, State.DisplayString as StateDisp, SUBQUERY(BasicSchemaObjectType AS t, t.Name, t.ID=base.TypeID) as CIName", $"[Expression-ObjectID] = '{ActivityEOID}'");
|
|
if (tbl3?.Rows == null || tbl3.Rows.Count <= 0)
|
|
{
|
|
LogEntry($"SPSCommonClassBase fragment not found: ClassId={SPSCommonClassBaseID}, ObjectId={ActivityEOID}", LogLevels.Debug);
|
|
continue;
|
|
}
|
|
|
|
var State = getIntFromObject(tbl3.Rows[0]["State"]);
|
|
var StateDisp = getStringFromObject(tbl3.Rows[0]["StateDisp"]);
|
|
var CIName = getStringFromObject(tbl3.Rows[0]["CIName"]);
|
|
|
|
dynamic viewOptionsDyn = new ExpandoObject();
|
|
viewOptionsDyn.objectId = ActivityEOID;
|
|
viewOptionsDyn.type = CIName;
|
|
viewOptionsDyn.viewType = "action";
|
|
viewOptionsDyn.actionId = TicketCloseActionId;
|
|
var viewOptions = HttpUtility.UrlEncode(JsonConvert.SerializeObject(viewOptionsDyn));
|
|
|
|
var ticketDirectLinkPreview = string.Format(TicketDirectLinkPreviewTemplate, F4SDM42WebApiController.defaultInstance.BaseUrl, CIName, ActivityEOID);
|
|
var ticketDirectLinkEdit = string.Format(TicketDirectLinkEditTemplate, F4SDM42WebApiController.defaultInstance.BaseUrl, CIName, ActivityEOID);
|
|
var ticketDirectLinkClose = string.Format(IncidentDirectLinkCloseTemplate, F4SDM42WebApiController.defaultInstance.BaseUrl, ActivityEOID, viewOptions);
|
|
|
|
LogEntry($"Activity found: ObjectID={ActivityEOID}, TicketNumber={TicketNumber}, Subject={Subject}, State={State}", LogLevels.Debug);
|
|
var ticket = new cF4SDTicket()
|
|
{
|
|
TicketObjectId = ActivityEOID,
|
|
Name = TicketNumber,
|
|
CIName = CIName,
|
|
StatusId = State,
|
|
Status = StateDisp,
|
|
Summary = Subject,
|
|
AffectedUserId = InitiatorId,
|
|
AffectedUser = Initiator,
|
|
CreationDate = CreatedDate,
|
|
ClosingDate = ClosedDate,
|
|
DescriptionHtml = DescriptionHtml,
|
|
Description = Description,
|
|
SolutionHtml = SolutionHtml,
|
|
Solution = Solution,
|
|
Priority = Priority,
|
|
PriorityId = PriorityId,
|
|
CreationSourceId = EntryBy,
|
|
CreationSource = EntryByDisp,
|
|
CategoryHierarchical = CategoryHierarchical,
|
|
CategoryId = CategoryId,
|
|
Category = Category,
|
|
DirectLinkPreview = ticketDirectLinkPreview,
|
|
Urgency = Urgency,
|
|
UrgencyId = UrgencyId,
|
|
Impact = Impact,
|
|
ImpactId = ImpactId
|
|
//JournalItems = GetJournalEntriesByEOID(ActivityEOID)
|
|
};
|
|
|
|
if (AssetObject != null)
|
|
{
|
|
ticket.AssetId = AssetId;
|
|
ticket.AssetName = Asset;
|
|
ticket.AssetDomain = AssetDomain;
|
|
ticket.AssetCIId = AssetObject.CIId;
|
|
ticket.AssetCIName = AssetObject.CIName;
|
|
ticket.AssetSKUAssetGroupId = AssetObject.SKUAssetGroupId;
|
|
ticket.AssetSKUAssetGroup = AssetObject.SKUAssetGroup;
|
|
ticket.AssetSKUTypeId = AssetObject.SKUTypeId;
|
|
ticket.AssetSKUType = AssetObject.SKUType;
|
|
}
|
|
|
|
if (ticket.StatusId != 204)
|
|
ticket.DirectLinkEdit = ticketDirectLinkEdit;
|
|
|
|
if ((CIName.ToUpper() == "SPSACTIVITYTYPEINCIDENT" || CIName.ToUpper() == "SPSACTIVITYTYPESERVICEREQUEST") && ticket.StatusId != 204)
|
|
ticket.DirectLinkClose = ticketDirectLinkClose;
|
|
|
|
tickets.Add(ticket);
|
|
}
|
|
|
|
tickets = tickets.OrderBy(x => x.CreationDate).ToList();
|
|
tickets.Reverse();
|
|
return tickets;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
internal async Task<List<cTicketJournalItem>> GetJournalEntries(Guid activityEOID)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
await Task.Delay(0);
|
|
List<cTicketJournalItem> journalEntries = new List<cTicketJournalItem>();
|
|
var entries = F4SDM42WebApiController.defaultInstance._journalService.GetJournalList(activityEOID, false, 0, 50, "<a href=\"#\" class=\"mx-object-journal--link {0} {1}\">{2}</a>", 120);
|
|
LogEntry($"{entries.Length} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
|
|
for (int i = 0; i < entries.Length; i++)
|
|
{
|
|
Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[i];
|
|
LogEntry($"Journal entry {i + 1}/{entries.Length}: ID={item.Id}, CreatedDate={item.CreatedDate}, CreatedBy={item.Creator}, Header={item.Header}", LogLevels.Debug);
|
|
journalEntries.Add(new cTicketJournalItem()
|
|
{
|
|
JournalId = item.Id,
|
|
ActivityObjectId = activityEOID,
|
|
CreatedBy = item.Creator,
|
|
CreationDate = (DateTime)item.CreatedDate,
|
|
DescriptionHtml = item.Text,
|
|
Description = Matrix42.Common.Html.HtmlConverter.ConvertHtmlToPlainText(item.Text),
|
|
Header = item.Header,
|
|
IsVisibleForUser = item.VisibleInPortal
|
|
});
|
|
}
|
|
return journalEntries;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
internal async Task<bool> updateActivitySolution(Guid objectId, string solutionHtml)
|
|
{
|
|
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
await Task.Delay(0);
|
|
if (objectId == Guid.Empty)
|
|
return false;
|
|
|
|
var tbl = FragmentRequestBase.SimpleLoad(SPSActivityClassBaseID, "ID", $"[Expression-ObjectID] = '{objectId}'");
|
|
if (tbl?.Rows == null || tbl.Rows.Count <= 0)
|
|
{
|
|
LogEntry($"SPSActivityClassBase fragment not found: ClassId={SPSActivityClassBaseID}, ObjectId={objectId}", LogLevels.Debug);
|
|
return false;
|
|
}
|
|
|
|
var fragmentId = getGuidFromObject(tbl.Rows[0]["ID"]);
|
|
SPSFragment activityFragment = ObjectBroker.GetFragment(SPSActivityClassBaseID, fragmentId);
|
|
activityFragment["SolutionHTML"] = solutionHtml;
|
|
ObjectBroker.UpdateFragment(SPSActivityClassBaseID, activityFragment);
|
|
return true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return false;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
private List<M42Asset> getAssetsByAsql(string Filter)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
// get SPSAssetClassBase
|
|
if (string.IsNullOrEmpty(Filter))
|
|
return null;
|
|
List<M42Asset> assets = new List<M42Asset>();
|
|
LogEntry($"ASql Filter: {Filter}");
|
|
var tbl = FragmentRequestBase.SimpleLoad(SPSAssetClassBaseID
|
|
, "Id" +
|
|
", COALESCE(T(SPSComputerClassBase).Name, T(SPSAssetClassSIMCard).PhoneNumber, Name) as AssetName" +
|
|
", SUBQUERY(BasicSchemaObjectType AS t, t.Name, t.ID=base.T(SPSCommonClassBase).TypeID) as CIName" +
|
|
", SUBQUERY(BasicSchemaObjectType AS t, t.Id, t.ID=base.T(SPSCommonClassBase).TypeID) as CIId" +
|
|
", SKU.Type as SKUTypeId" +
|
|
", SKU.Type.DisplayString as SKUType" +
|
|
", SKU.Type.AssetGroup as SKUAssetGroupId" +
|
|
", SUBQUERY(SPSAssetPickupTypeCategory AS ag, ag.DisplayString, ag.Value=base.SKU.Type.AssetGroup) as SKUAssetGroup" +
|
|
", T(SPSComputerClassAD).Domain.NT4Name as DomainName" +
|
|
", T(SPSComputerClassAD).Sid as Sid"
|
|
, Filter);
|
|
if (tbl?.Rows == null || tbl.Rows.Count <= 0)
|
|
{
|
|
LogEntry($"SPSAssetClassBase fragment not found: ClassId={SPSActivityClassIncidentID}, Filter={Filter}", LogLevels.Debug);
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
foreach (DataRow row in tbl.Rows)
|
|
{
|
|
var asset = new M42Asset()
|
|
{
|
|
Id = getGuidFromObject(row["Id"]),
|
|
Name = getStringFromObject(row["AssetName"]),
|
|
CIName = getStringFromObject(row["CIName"]),
|
|
CIId = getGuidFromObject(row["CIId"]),
|
|
SKUTypeId = getIntFromObject(row["SKUTypeId"]),
|
|
SKUType = getStringFromObject(row["SKUType"]),
|
|
SKUAssetGroupId = getIntFromObject(row["SKUAssetGroupId"]),
|
|
SKUAssetGroup = getStringFromObject(row["SKUAssetGroup"]),
|
|
DomainName = getStringFromObject(row["DomainName"]),
|
|
Sid = getStringFromObject(row["Sid"]),
|
|
};
|
|
assets.Add(asset);
|
|
LogEntry($"Asset found: Id={asset.Id}, Name={asset.Name}, CIName={asset.CIName}", LogLevels.Debug);
|
|
}
|
|
}
|
|
return assets;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
private M42Asset getAssetByName(string assetname)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
// get SPSAssetClassBase
|
|
if (string.IsNullOrEmpty(assetname))
|
|
return null;
|
|
var Filter = string.Format("T(SPSComputerClassBase).Name = '{0}' OR T(SPSAssetClassSIMCard).PhoneNumber = '{0}' OR Name = '{0}'", assetname);
|
|
return getAssetsByAsql(Filter)?.First();
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
private Guid getUserBySid(string sid)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
string sidPattern = @"^S-\d-\d+-(\d+-){1,14}\d+$";
|
|
if (string.IsNullOrEmpty(sid) || !Regex.IsMatch(sid, sidPattern))
|
|
{
|
|
LogEntry($"Invalid or empty SID: '{sid}'", LogLevels.Warning);
|
|
return Guid.Empty;
|
|
}
|
|
|
|
var users = getUsersByAsql(string.Format("Accounts.T(SPSAccountClassAD).Sid = '{0}' OR PrimaryAccount.T(SPSAccountClassAD).Sid = '{0}'", sid));
|
|
return users != null ? users.First().Id : Guid.Empty;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return Guid.Empty;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
|
|
private List<M42User> getUsersByAsql(string asqlFilter)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
var Persons = new List<M42User>();
|
|
|
|
|
|
LogEntry($"ASql Filter: {asqlFilter}");
|
|
|
|
var tbl = FragmentRequestBase.SimpleLoad(SPSUserClassBaseID,
|
|
"Id as Id" +
|
|
", [Expression-ObjectID] as UserEOID" +
|
|
", T(SPSCommonClassBase).State as State" +
|
|
", LastName + ISNULL(', ' + FirstName,'') as Name" +
|
|
", PreferredMailCulture.Locale as Locale" +
|
|
", T(SPSCommonClassBase).State.DisplayString as StateDisp",
|
|
asqlFilter);
|
|
if (tbl?.Rows == null || tbl.Rows.Count <= 0)
|
|
{
|
|
LogEntry($"no user entry list found with asql='{asqlFilter}'", LogLevels.Warning);
|
|
return null;
|
|
}
|
|
foreach (DataRow Entry in tbl.Rows)
|
|
{
|
|
// get the id
|
|
var UserId = getGuidFromObject(Entry["ID"]);
|
|
if (UserId == Guid.Empty)
|
|
{
|
|
LogEntry($"no id found for user entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
var UserEOID = getGuidFromObject(Entry["UserEOID"]);
|
|
if (UserEOID == Guid.Empty)
|
|
{
|
|
LogEntry($"no expression object id found for user entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
var Name = getStringFromObject(Entry["Name"]);
|
|
if (string.IsNullOrEmpty(Name))
|
|
{
|
|
LogEntry($"no Name found for entry", LogLevels.Debug);
|
|
}
|
|
var Locale = getStringFromObject(Entry["Locale"]);
|
|
if (string.IsNullOrEmpty(Locale))
|
|
{
|
|
LogEntry($"no locale found for entry", LogLevels.Debug);
|
|
}
|
|
var StateDisp = getStringFromObject(Entry["StateDisp"]);
|
|
if (string.IsNullOrEmpty(StateDisp))
|
|
{
|
|
LogEntry($"no statedisp found for entry", LogLevels.Debug);
|
|
}
|
|
|
|
|
|
|
|
var State = getIntFromObject(Entry["State"]);
|
|
LogEntry($"User found: ID={UserId}, ObjectID={UserEOID}, State={State}", LogLevels.Debug);
|
|
if (State != 2023)
|
|
LogEntry($"User is not active", LogLevels.Debug);
|
|
Persons.Add(new M42User()
|
|
{
|
|
Id = UserId,
|
|
ObjectId = UserEOID,
|
|
Name = Name,
|
|
State = State,
|
|
Locale = Locale,
|
|
LanguageId = new CultureInfo(Locale).LCID % 1024,
|
|
StateDisp = StateDisp
|
|
});
|
|
}
|
|
return Persons;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
private List<M42Account> getAccountsByAsql(string asqlFilter)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
var result = new List<M42Account>();
|
|
|
|
|
|
LogEntry($"ASql Filter: {asqlFilter}");
|
|
|
|
var tbl = FragmentRequestBase.SimpleLoad(SPSAccountClassBaseID,
|
|
"Id as Id" +
|
|
", [Expression-ObjectID] as EOID" +
|
|
", T(SPSCommonClassBase).State as State" +
|
|
", T(SPSAccountClassAD).Sid as Sid" +
|
|
", T(SPSAccountClassAD).UserPrincipalName as UserPrincipalName" +
|
|
", Owner ",
|
|
asqlFilter);
|
|
if (tbl?.Rows == null || tbl.Rows.Count <= 0)
|
|
{
|
|
LogEntry($"no account entry list found with asql='{asqlFilter}'", LogLevels.Warning);
|
|
return null;
|
|
}
|
|
foreach (DataRow Entry in tbl.Rows)
|
|
{
|
|
// get the id
|
|
var Id = getGuidFromObject(Entry["ID"]);
|
|
if (Id == Guid.Empty)
|
|
{
|
|
LogEntry($"no id found for entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
var EOID = getGuidFromObject(Entry["EOID"]);
|
|
if (EOID == Guid.Empty)
|
|
{
|
|
LogEntry($"no expression object id found for entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
var Owner = getGuidFromObject(Entry["Owner"]);
|
|
if (Owner == Guid.Empty)
|
|
{
|
|
LogEntry($"no owner found for entry", LogLevels.Warning);
|
|
}
|
|
var Sid = getStringFromObject(Entry["Sid"]);
|
|
if (string.IsNullOrEmpty(Sid))
|
|
{
|
|
LogEntry($"no Sid found for entry", LogLevels.Debug);
|
|
}
|
|
var UserPrincipalName = getStringFromObject(Entry["UserPrincipalName"]);
|
|
if (string.IsNullOrEmpty(UserPrincipalName))
|
|
{
|
|
LogEntry($"no UserPrincipalName found for entry", LogLevels.Debug);
|
|
}
|
|
|
|
|
|
var State = getIntFromObject(Entry["State"]);
|
|
LogEntry($"Account found: ID={Id}, ObjectID={EOID}, State={State}", LogLevels.Debug);
|
|
result.Add(new M42Account()
|
|
{
|
|
Id = Id,
|
|
EOID = EOID,
|
|
State = State,
|
|
UserPrincipalName = UserPrincipalName,
|
|
Sid = Sid,
|
|
Owner = Owner
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
internal HttpResponseMessage privGetLog(string download, int maxLines, HttpRequestMessage request, string filter)
|
|
{
|
|
var response = new HttpResponseMessage();
|
|
|
|
|
|
|
|
if (download == "1")
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
var logger = (DefaultLogger.Manager as cLogManagerFile);
|
|
var logFileName = logger.GetLogFileName();
|
|
MemoryStream memoryStream = new MemoryStream();
|
|
|
|
ZipArchive zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: true);
|
|
string[] files = Directory.GetFiles(Path.GetDirectoryName(logFileName), $"*.log");
|
|
foreach (string fileName in files)
|
|
{
|
|
using (var tmpInStream = new FileStream(logFileName, FileMode.Open,
|
|
FileAccess.Read, FileShare.ReadWrite))
|
|
{
|
|
ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry(Path.GetFileName(fileName));
|
|
using (Stream destination = zipArchiveEntry.Open())
|
|
{
|
|
tmpInStream.CopyTo(destination);
|
|
}
|
|
}
|
|
}
|
|
zipArchive.Dispose();
|
|
memoryStream.Position = 0L;
|
|
HttpResponseMessage httpResponseMessage = request.CreateResponse(HttpStatusCode.OK);
|
|
httpResponseMessage.Content = new StreamContent(memoryStream);
|
|
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
|
|
{
|
|
FileName = Path.GetFileNameWithoutExtension(logFileName) + ".zip"
|
|
};
|
|
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
|
|
|
return httpResponseMessage;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
var logger = (DefaultLogger.Manager as cLogManagerFile);
|
|
var logFileName = logger.GetLogFileName();
|
|
using (var inStream = new FileStream(logFileName, FileMode.Open,
|
|
FileAccess.Read, FileShare.ReadWrite))
|
|
{
|
|
var lines = ReadLines(() => inStream,
|
|
Encoding.UTF8)
|
|
.ToList();
|
|
var sb = new StringBuilder();
|
|
sb.AppendLine("<html><body><table>");
|
|
var htmlLines = new List<string>();
|
|
foreach (var line in lines)
|
|
{
|
|
var lineSplit = line.Split('\t');
|
|
if (string.IsNullOrEmpty(filter) || !string.IsNullOrEmpty(filter) && lineSplit.Length > 4 && filter.ToLowerInvariant().Split(',').Contains(lineSplit[3].ToLowerInvariant()))
|
|
htmlLines.Add("<tr><td><nobr>" + string.Join("</nobr></td><td><nobr>", lineSplit) + "</nobr></td></tr>");
|
|
}
|
|
if (maxLines > 0)
|
|
htmlLines = htmlLines.Skip(Math.Max(0, htmlLines.Count() - maxLines)).ToList();
|
|
foreach (var line in htmlLines)
|
|
{
|
|
sb.AppendLine(line);
|
|
}
|
|
sb.AppendLine("</table></body></html>");
|
|
|
|
response.Content = new StringContent(sb.ToString());
|
|
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html")
|
|
{
|
|
CharSet = Encoding.UTF8.HeaderName
|
|
};
|
|
response.Content.Headers.Add("CodePage", Encoding.UTF8.CodePage.ToString());
|
|
return response;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal List<cM42LogEntry> privGetLog2()
|
|
{
|
|
var response = new HttpResponseMessage();
|
|
{
|
|
var logger = (DefaultLogger.Manager as cLogManagerFile);
|
|
var logFileName = logger.GetLogFileName();
|
|
using (var inStream = new FileStream(logFileName, FileMode.Open,
|
|
FileAccess.Read, FileShare.ReadWrite))
|
|
{
|
|
var lines = ReadLines(() => inStream,
|
|
Encoding.UTF8)
|
|
.ToList();
|
|
|
|
var entries = new List<cM42LogEntry>();
|
|
DateTime dateValue;
|
|
for (int i = 0; i < lines.Count; i++)
|
|
{
|
|
string line = lines[i];
|
|
try
|
|
{
|
|
var lineSplit = line.Split('\t');
|
|
if (lineSplit.Length >= 5)
|
|
{
|
|
if (string.IsNullOrEmpty(lineSplit[0]))
|
|
{
|
|
entries.Last().Message += Environment.NewLine + lineSplit[4];
|
|
continue;
|
|
}
|
|
DateTime.TryParseExact(lineSplit[0], "yyyy-MM-dd HH:mm:ss:fffff", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateValue);
|
|
entries.Add(new cM42LogEntry()
|
|
{
|
|
LineNumber = i + 1,
|
|
date = dateValue,
|
|
ProcessId = lineSplit[1],
|
|
logLvl = lineSplit[3],
|
|
Theme = lineSplit[2],
|
|
Message = lineSplit[4],
|
|
});
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
|
|
}
|
|
}
|
|
return entries;
|
|
}
|
|
}
|
|
}
|
|
|
|
private int getIntFromObject(object o, int Default = 0)
|
|
{
|
|
try
|
|
{
|
|
if (o == null)
|
|
return Default;
|
|
if (o is DBNull)
|
|
return Default;
|
|
if (o is int @int)
|
|
return @int;
|
|
if (o is long int1)
|
|
return (int)int1;
|
|
if (int.TryParse(o.ToString(), out var r))
|
|
return r;
|
|
}
|
|
catch { }
|
|
return Default;
|
|
}
|
|
|
|
private DateTime getDateTimeFromObject(object o)
|
|
{
|
|
try
|
|
{
|
|
if (o == null)
|
|
return DateTime.MinValue;
|
|
if (o is DBNull)
|
|
return DateTime.MinValue;
|
|
if (o is DateTime @dateTime)
|
|
return @dateTime;
|
|
if (o is string dstr && DateTime.TryParse(o.ToString(), out var r))
|
|
return r;
|
|
}
|
|
catch { }
|
|
return DateTime.MinValue;
|
|
}
|
|
|
|
private string getStringFromObject(object o, string Default = "")
|
|
{
|
|
try
|
|
{
|
|
if (o == null)
|
|
return Default;
|
|
if (o is DBNull)
|
|
return Default;
|
|
return o.ToString();
|
|
}
|
|
catch { }
|
|
return Default;
|
|
}
|
|
|
|
private Guid getGuidFromObject(object o)
|
|
{
|
|
try
|
|
{
|
|
if (o == null)
|
|
return Guid.Empty;
|
|
if (o is DBNull)
|
|
return Guid.Empty;
|
|
if (o is Guid G)
|
|
return G;
|
|
if (Guid.TryParse(o.ToString(), out var r))
|
|
return r;
|
|
}
|
|
catch { }
|
|
return Guid.Empty;
|
|
}
|
|
|
|
internal cM42LogEntry privGetLog2(int id)
|
|
{
|
|
return privGetLog2().Find(x => x.LineNumber == id);
|
|
}
|
|
|
|
internal async Task<List<M42Role>> getRoleMembershipById(Guid UserId)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
var RoleMemberships = new List<M42Role>();
|
|
try
|
|
{
|
|
await Task.Delay(0);
|
|
var asqlFilter = string.Format("Members.Id = '{0}'", UserId.ToString());
|
|
LogEntry($"ASql Filter: {asqlFilter}");
|
|
|
|
FragmentRequestBase fragmentRequestBase = new FragmentRequestBase(SPSSecurityClassRole, ColumnSelectOption.List, "Id as Id" +
|
|
", Name as Name");
|
|
fragmentRequestBase.Where = asqlFilter;
|
|
var langExt = new FragmentRequestExtensionLanguage();
|
|
langExt.AddCultureRequest(new CultureInfo("en"));
|
|
fragmentRequestBase.AddExtension(langExt);
|
|
|
|
using (SPSTransactionScope sPSTransactionScope = new SPSTransactionScope(SPSTransactionScopeOption.Required, new SPSTransactionOptions(IsolationLevel.ReadUncommitted)))
|
|
{
|
|
fragmentRequestBase.Load();
|
|
sPSTransactionScope.Complete();
|
|
}
|
|
|
|
// if requested language is already "en" use the english table
|
|
var tbl = fragmentRequestBase.DataSet.Tables[1];
|
|
if (tbl?.Rows == null || tbl.Rows.Count <= 0)
|
|
tbl = fragmentRequestBase.DataSet.Tables[0];
|
|
if (tbl?.Rows == null || tbl.Rows.Count <= 0)
|
|
{
|
|
LogEntry($"no role membership found with asql='{asqlFilter}'", LogLevels.Debug);
|
|
return RoleMemberships;
|
|
}
|
|
foreach (DataRow Entry in tbl.Rows)
|
|
{
|
|
if (Entry.Table.Columns.Contains("LCID") && (int)Entry["LCID"] != 9)
|
|
continue;
|
|
// get the id
|
|
var IDColumn = Entry.Table.Columns.Contains("Owner") ? "Owner" : "ID";
|
|
var RoleId = getGuidFromObject(Entry[IDColumn]);
|
|
if (RoleId == Guid.Empty)
|
|
{
|
|
LogEntry($"no id found for role entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
var Name = getStringFromObject(Entry["Name"]);
|
|
if (string.IsNullOrEmpty(Name))
|
|
{
|
|
LogEntry($"no Name found for entry", LogLevels.Debug);
|
|
}
|
|
LogEntry($"Role Membership found: ID={RoleId}, Name={Name}", LogLevels.Debug);
|
|
RoleMemberships.Add(new M42Role() { Id = RoleId, Name = Name });
|
|
}
|
|
return RoleMemberships;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
/*
|
|
internal async Task<List<M42Role>> getRoleMembershipById(Guid UserId)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
var RoleMemberships = new List<M42Role>();
|
|
try
|
|
{
|
|
await Task.Delay(0);
|
|
var asqlFilter = string.Format("Members.Id = '{0}'", UserId.ToString());
|
|
LogEntry($"ASql Filter: {asqlFilter}");
|
|
var tbl = FragmentRequestBase.SimpleLoad(SPSSecurityClassRole,
|
|
"Id as Id" +
|
|
", Name as Name",
|
|
asqlFilter);
|
|
if (tbl?.Rows == null || tbl.Rows.Count <= 0)
|
|
{
|
|
LogEntry($"no role membership found with asql='{asqlFilter}'", LogLevels.Debug);
|
|
return RoleMemberships;
|
|
}
|
|
foreach (DataRow Entry in tbl.Rows)
|
|
{
|
|
// get the id
|
|
var RoleId = getGuidFromObject(Entry["ID"]);
|
|
if (RoleId == Guid.Empty)
|
|
{
|
|
LogEntry($"no id found for role entry", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
var Name = getStringFromObject(Entry["Name"]);
|
|
if (string.IsNullOrEmpty(Name))
|
|
{
|
|
LogEntry($"no Name found for entry", LogLevels.Debug);
|
|
}
|
|
LogEntry($"Role Membership found: ID={RoleId}, Name={Name}", LogLevels.Debug);
|
|
RoleMemberships.Add(new M42Role() { Id = RoleId, Name = Name });
|
|
}
|
|
return RoleMemberships;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
*/
|
|
internal async Task<object> UserPermissionsInfo(string filter)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
var RoleMemberships = new List<M42Role>();
|
|
try
|
|
{
|
|
await Task.Delay(0);
|
|
|
|
var retVal = new UserPermissionsInfo();
|
|
List<M42User> m42Users = getUsersByAsql(filter);
|
|
if (m42Users != null && m42Users.Count == 1)
|
|
{
|
|
retVal.User = m42Users[0];
|
|
|
|
|
|
var user = F4SDM42WebApiController.defaultInstance._userProfile.GetInteractiveUserInfo(retVal.User.Id);
|
|
if (user != null)
|
|
{
|
|
retVal.User.Id = user.Id;
|
|
retVal.User.Currency = user.Currency;
|
|
retVal.User.Email = user.Email;
|
|
retVal.User.FirstName = user.FirstName;
|
|
retVal.User.LastName = user.LastName;
|
|
retVal.User.Phone = user.Phone;
|
|
retVal.User.Photo = user.Photo;
|
|
}
|
|
|
|
retVal.Roles = await getRoleMembershipById(retVal.User.Id);
|
|
retVal.User.IsAdmin = retVal.Roles?.Where(i => i.Id == Administrators).FirstOrDefault() != null;
|
|
return retVal;
|
|
}
|
|
return null;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
private enum eM42EntryBy
|
|
{
|
|
Phone = 0,
|
|
Email = 1,
|
|
Portal = 2,
|
|
CatalogOrder = 3,
|
|
EventTrigger = 4,
|
|
Feedback = 5,
|
|
VisualSupportAgent = 6,
|
|
ComplianceAlert = 7,
|
|
F4SD = 20010,
|
|
}
|
|
|
|
public class DirectLink
|
|
{
|
|
public string Link { get; set; }
|
|
public string SubjectParameter { get; set; }
|
|
public string DescriptionParameter { get; set; }
|
|
}
|
|
|
|
public class M42Asset
|
|
{
|
|
public Guid Id { get; set; }
|
|
public string Name { get; set; }
|
|
public string CIName { get; set; }
|
|
public string SKUType { get; set; }
|
|
public string SKUAssetGroup { get; set; }
|
|
public Guid CIId { get; set; }
|
|
public int SKUTypeId { get; internal set; }
|
|
public int SKUAssetGroupId { get; internal set; }
|
|
public string DomainName { get; internal set; }
|
|
public string Sid { get; internal set; }
|
|
}
|
|
}
|
|
|
|
public class M42User
|
|
{
|
|
public Guid Id { get; internal set; }
|
|
public Guid ObjectId { get; internal set; }
|
|
public string Name { get; internal set; }
|
|
public string FirstName { get; internal set; }
|
|
public string LastName { get; internal set; }
|
|
public string Email { get; internal set; }
|
|
public string Photo { get; internal set; }
|
|
public string Phone { get; internal set; }
|
|
public string Currency { get; internal set; }
|
|
public string Locale { get; internal set; }
|
|
public int LanguageId { get; internal set; }
|
|
public bool IsAdmin { get; internal set; }
|
|
public int State { get; internal set; }
|
|
public string StateDisp { get; internal set; }
|
|
}
|
|
|
|
internal class M42Account
|
|
{
|
|
public Guid Id { get; internal set; }
|
|
public Guid EOID { get; internal set; }
|
|
public Guid Owner { get; internal set; }
|
|
public int State { get; internal set; }
|
|
public string UserPrincipalName { get; internal set; }
|
|
public string Sid { get; internal set; }
|
|
}
|
|
|
|
public class M42Role
|
|
{
|
|
public Guid Id { get; internal set; }
|
|
public string Name { get; internal set; }
|
|
|
|
}
|
|
|
|
public class UserPermissionsInfo
|
|
{
|
|
public M42User User { get; internal set; }
|
|
public List<M42Role> Roles { get; internal set; }
|
|
public UserPermissionsInfo()
|
|
{
|
|
User = new M42User();
|
|
Roles = new List<M42Role>();
|
|
}
|
|
}
|
|
}
|