- update multiple LIAM projects and solution/config files - add LiamWorkflowDiagnostics app sources and generated outputs - include current workspace state (dependencies and build outputs)
554 lines
17 KiB
C#
554 lines
17 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using C4IT.Logging;
|
|
using static C4IT.Logging.cLogManager;
|
|
namespace C4IT.LIAM
|
|
{
|
|
public static class LiamInitializer
|
|
{
|
|
static public cLiamProviderBase CreateInstance(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData)
|
|
{
|
|
return new cLiamProviderFileshare(LiamConfiguration, ProviderData);
|
|
}
|
|
}
|
|
|
|
public class cLiamProviderFileshare : cLiamProviderBase
|
|
{
|
|
public readonly cFile MsSharepoint = new cMsGraphSharepoint(new cMsGraphBase());
|
|
public Exception LastException { get; private set; } = null;
|
|
public string LastErrorMessage { get; private set; } = null;
|
|
public bool IsOnline { get; private set; } = false;
|
|
public string AccessToken { get; private set; } = null;
|
|
public DateTime TokenExpiresIn { get; private set; } = DateTime.MinValue;
|
|
private cFileshareLogonInfo privLogonInfo = null;
|
|
|
|
public cLiamProviderFileshare(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData) :
|
|
base(LiamConfiguration, ProviderData)
|
|
{ }
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void ResetError()
|
|
{
|
|
LastException = null;
|
|
LastErrorMessage = null;
|
|
}
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void SetErrorException(string Action, Exception E, LogLevels lev = LogLevels.Error)
|
|
{
|
|
LastException = E;
|
|
LastErrorMessage = Action + ": " + E.Message;
|
|
cLogManager.LogEntry(Action, lev);
|
|
}
|
|
public override async Task<cLiamDataAreaBase> LoadDataArea(string UID)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
await Task.Delay(0);
|
|
try
|
|
{
|
|
var lstIds = UID.Split('|');
|
|
|
|
|
|
|
|
return null;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
|
|
}
|
|
public override async Task<List<cLiamDataAreaBase>> getDataAreasAsync(int Depth = -1)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
if (!await LogonAsync())
|
|
return null;
|
|
|
|
var DataAreas = new List<cLiamDataAreaBase>();
|
|
|
|
var DAL = await MsSharepoint.RequestTeamsListAsync();
|
|
if (DAL == null)
|
|
return null;
|
|
|
|
foreach (var Entry in DAL)
|
|
{
|
|
if (!string.IsNullOrEmpty(this.DataAreaRegEx) && !Regex.Match(Entry.Key, this.DataAreaRegEx).Success)
|
|
continue;
|
|
|
|
var MsTeam = await MsSharepoint.RequestGroupInfoAsync(Entry.Value);
|
|
if (MsTeam == null)
|
|
continue;
|
|
|
|
var Team = new cLiamMsTeamsTeam(this, MsTeam);
|
|
DataAreas.Add(Team);
|
|
}
|
|
|
|
if (Depth > 0)
|
|
{
|
|
var allChilds = new List<cLiamDataAreaBase>();
|
|
foreach (var Entry in DataAreas)
|
|
{
|
|
var entryChilds = await (Entry as cLiamMsTeamsTeam).getChannels(true);
|
|
if (entryChilds != null && entryChilds.Count > 0)
|
|
allChilds.AddRange(entryChilds);
|
|
}
|
|
DataAreas.AddRange(allChilds);
|
|
}
|
|
|
|
return DataAreas;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
public override async Task<bool> LogonAsync()
|
|
{
|
|
return await LogonAsync(true);
|
|
}
|
|
public async Task<bool> LogonAsync(bool force = false)
|
|
{
|
|
if (!force && IsOnline)
|
|
return true;
|
|
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
var LI = new cFileshareLogonInfo()
|
|
{
|
|
Domain = this.Domain,
|
|
User = this.Credential?.Identification,
|
|
UserSecret = this.Credential?.Secret,
|
|
TargetNetworkName = this.RootPath
|
|
};
|
|
var RetVal = await LogonAsync(LI);
|
|
return RetVal;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
private async Task<bool> privRelogon()
|
|
{
|
|
if (DateTime.UtcNow < TokenExpiresIn)
|
|
return true;
|
|
if (privLogonInfo == null)
|
|
return false;
|
|
var RetVal = await privLogonAsync(privLogonInfo);
|
|
return RetVal;
|
|
}
|
|
|
|
public async Task<bool> LogonAsync(cFileshareLogonInfo LogonInfo)
|
|
{
|
|
var RetVal = await privLogonAsync(LogonInfo);
|
|
if (RetVal == true)
|
|
privLogonInfo = LogonInfo;
|
|
return RetVal;
|
|
}
|
|
private async Task<bool> privLogonAsync(cFileshareLogonInfo LogonInfo)
|
|
{
|
|
//TODO: remove dummy delay?
|
|
await Task.Delay(0);
|
|
try
|
|
{
|
|
ResetError();
|
|
IsOnline = false;
|
|
|
|
var netResource = new NetResource()
|
|
{
|
|
Scope = ResourceScope.GlobalNetwork,
|
|
ResourceType = ResourceType.Disk,
|
|
DisplayType = ResourceDisplaytype.Share,
|
|
RemoteName = LogonInfo.TargetNetworkName
|
|
};
|
|
|
|
var result = WNetAddConnection2(
|
|
netResource,
|
|
LogonInfo.UserSecret,
|
|
LogonInfo.User,
|
|
0);
|
|
|
|
if (result != 0)
|
|
{
|
|
//DefaultLogger.LogEntry(LogLevels.Debug, $"Error in connect occured ({result}) {new Win32Exception(result).Message}");
|
|
//throw new Win32Exception(result);
|
|
return false;
|
|
}
|
|
|
|
IsOnline = true;
|
|
return true;
|
|
|
|
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
SetErrorException("exception error while network drive login", E, LogLevels.Debug);
|
|
cLogManager.LogException(E, LogLevels.Debug);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
[DllImport("mpr.dll")]
|
|
private static extern int WNetAddConnection2(NetResource netResource,
|
|
string password, string username, int flags);
|
|
|
|
}
|
|
|
|
public class cFileshareLogonInfo
|
|
{
|
|
public string Domain;
|
|
public string User;
|
|
public string UserSecret;
|
|
public string TargetNetworkName;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public class NetResource
|
|
{
|
|
public ResourceScope Scope;
|
|
public ResourceType ResourceType;
|
|
public ResourceDisplaytype DisplayType;
|
|
public int Usage;
|
|
public string LocalName;
|
|
public string RemoteName;
|
|
public string Comment;
|
|
public string Provider;
|
|
}
|
|
|
|
public enum ResourceScope : int
|
|
{
|
|
Connected = 1,
|
|
GlobalNetwork,
|
|
Remembered,
|
|
Recent,
|
|
Context
|
|
};
|
|
|
|
public enum ResourceType : int
|
|
{
|
|
Any = 0,
|
|
Disk = 1,
|
|
Print = 2,
|
|
Reserved = 8,
|
|
}
|
|
|
|
public enum ResourceDisplaytype : int
|
|
{
|
|
Generic = 0x0,
|
|
Domain = 0x01,
|
|
Server = 0x02,
|
|
Share = 0x03,
|
|
File = 0x04,
|
|
Group = 0x05,
|
|
Network = 0x06,
|
|
Root = 0x07,
|
|
Shareadmin = 0x08,
|
|
Directory = 0x09,
|
|
Tree = 0x0a,
|
|
Ndscontainer = 0x0b
|
|
}
|
|
|
|
public enum NetError : uint
|
|
{
|
|
NERR_Success = 0,
|
|
NERR_BASE = 2100,
|
|
NERR_UnknownDevDir = (NERR_BASE + 16),
|
|
NERR_DuplicateShare = (NERR_BASE + 18),
|
|
NERR_BufTooSmall = (NERR_BASE + 23),
|
|
}
|
|
public enum SHARE_TYPE : uint
|
|
{
|
|
STYPE_DISKTREE = 0,
|
|
STYPE_PRINTQ = 1,
|
|
STYPE_DEVICE = 2,
|
|
STYPE_IPC = 3,
|
|
STYPE_SPECIAL = 0x80000000,
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
|
public struct SHARE_INFO_1
|
|
{
|
|
public string shi1_netname;
|
|
public uint shi1_type;
|
|
public string shi1_remark;
|
|
public SHARE_INFO_1(string sharename, uint sharetype, string remark)
|
|
{
|
|
this.shi1_netname = sharename;
|
|
this.shi1_type = sharetype;
|
|
this.shi1_remark = remark;
|
|
}
|
|
public override string ToString()
|
|
{
|
|
return shi1_netname;
|
|
}
|
|
}
|
|
|
|
public class cLiamNtfsShare : cLiamDataAreaBase
|
|
{
|
|
public new readonly cLiamProviderFileshare Provider = null;
|
|
|
|
private readonly cMsGraphResultGroup MsTeam = null;
|
|
|
|
public cLiamMsTeamsTeam(cLiamProviderMsTeams Provider, cMsGraphResultGroup MsTeam) :
|
|
base(Provider)
|
|
{
|
|
this.Provider = Provider;
|
|
this.MsTeam = MsTeam;
|
|
|
|
this.TechnicalName = MsTeam.DisplayName;
|
|
this.Level = 0;
|
|
this.UID = getUID(MsTeam.ID);
|
|
this.ParentUID = "";
|
|
this.DataType = eLiamDataAreaTypes.MsTeamsTeam;
|
|
this.SupportsOwners = true;
|
|
this.SupportsPermissions = true;
|
|
}
|
|
|
|
internal static string getUID(string TeamID)
|
|
{
|
|
return $"{TeamID}";
|
|
}
|
|
|
|
internal async Task<List<cLiamDataAreaBase>> getChannels(bool OnlyPrivate)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
if (MsTeam == null)
|
|
return null;
|
|
|
|
var RegExFilter = this.Provider?.DataAreaRegEx;
|
|
var SP = this.Provider?.MsSharepoint;
|
|
var WithoutPrivateChannels = this.Provider?.WithoutPrivateChannels ?? false;
|
|
|
|
if (MsTeam.Channels == null)
|
|
if (SP == null || !await MsTeam.ResolveChannels(SP, OnlyPrivate))
|
|
return null;
|
|
|
|
var RetVal = new List<cLiamDataAreaBase>(MsTeam.Channels.Count);
|
|
foreach (var Entry in MsTeam.Channels.Values)
|
|
{
|
|
if (!string.IsNullOrEmpty(RegExFilter) && !Regex.Match(Entry.DisplayName, RegExFilter).Success)
|
|
continue;
|
|
if (WithoutPrivateChannels && !string.IsNullOrEmpty(Entry.MembershipType) && Entry.MembershipType == "private")
|
|
continue;
|
|
|
|
var DA = new cLiamMsTeamsChannel(Provider, this, Entry);
|
|
RetVal.Add(DA);
|
|
}
|
|
|
|
return RetVal;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
var RetVal = await getChannels(false);
|
|
if (RetVal != null)
|
|
RetVal.AddRange(await getChildrenFromListAsync(RetVal, Depth));
|
|
|
|
return RetVal;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
public static async Task<cLiamMsTeamsTeam> Load(cLiamProviderMsTeams Provider, string UID)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
var arrIDs = UID.Split('|');
|
|
if (arrIDs.Length != 1)
|
|
return null;
|
|
|
|
var TeamID = cLiamProviderMsTeams.getUidItem(ref UID);
|
|
|
|
var T = await Provider.MsSharepoint.RequestGroupInfoAsync(TeamID);
|
|
if (T == null)
|
|
return null;
|
|
|
|
var RetVal = new cLiamMsTeamsTeam(Provider, T);
|
|
|
|
return RetVal;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
public class cNtfsResultBase
|
|
{
|
|
public string ID { get; private set; } = null;
|
|
public string DisplayName { get; private set; } = null;
|
|
public dynamic Result { get; private set; } = null;
|
|
|
|
public cNtfsResultBase(dynamic Result)
|
|
{
|
|
this.Result = Result;
|
|
}
|
|
|
|
public cNtfsResultBase(cNtfsResultBase Result)
|
|
{
|
|
if (Result == null)
|
|
return;
|
|
|
|
this.Result = Result.Result;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static string GetStringFromDynamic(dynamic O, string ProperyName)
|
|
{
|
|
try
|
|
{
|
|
return (string)O[ProperyName];
|
|
}
|
|
catch { }
|
|
return null;
|
|
}
|
|
}
|
|
public class cLiamNtfsFolder : cLiamDataAreaBase
|
|
{
|
|
public new readonly cLiamProviderFileshare Provider = null;
|
|
public readonly cLiamNtfsShare Share = null;
|
|
public readonly cMsGraphResultFileObject MsFolder = null;
|
|
|
|
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
if (MsFolder == null)
|
|
return null;
|
|
|
|
var RegExFilter = this.Provider?.DataAreaRegEx;
|
|
var SP = this.Provider?.MsSharepoint;
|
|
|
|
if (MsFolder.Folders == null)
|
|
if (SP == null || !await MsFolder.ResolveFolders(SP))
|
|
return null;
|
|
|
|
var DataAreas = new List<cLiamDataAreaBase>();
|
|
foreach (var Entry in MsFolder.Folders.Values)
|
|
{
|
|
if (!string.IsNullOrEmpty(RegExFilter) && !Regex.Match(Entry.DisplayName, RegExFilter).Success)
|
|
continue;
|
|
|
|
var DA = new cLiamMsTeamsFolder(this.Provider, this.Channel, this, Entry, this.ChannelUID);
|
|
DataAreas.Add(DA);
|
|
}
|
|
var CL = await getChildrenFromListAsync(DataAreas, Depth);
|
|
if (CL != null)
|
|
DataAreas.AddRange(CL);
|
|
|
|
return DataAreas;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
public static async Task<cLiamMsTeamsFolder> Load(cLiamProviderMsTeams Provider, string UID)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
var arrIDs = UID.Split('|');
|
|
if (arrIDs.Length != 4)
|
|
return null;
|
|
|
|
var FolderID = cLiamProviderMsTeams.getUidItem(ref UID);
|
|
var DriveID = cLiamProviderMsTeams.getUidItem(ref UID);
|
|
|
|
var F = await Provider.MsSharepoint.RequestFileObjectInfo(DriveID, FolderID);
|
|
if (F == null)
|
|
return null;
|
|
|
|
var RetVal = new cLiamMsTeamsFolder(Provider, null, null, F, UID);
|
|
|
|
return RetVal;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|