using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web; using Newtonsoft.Json.Linq; using C4IT.Logging; using System.Reflection; using static C4IT.Logging.cLogManager; using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace C4IT.MsGraph { public class cMsGraphSharepoint { public const string constMsGraphTeamsList = "groups/?$filter=resourceProvisioningOptions/Any(x:x eq 'Team')&$select=id,displayName"; public const string constMsGraphGroupInfo = "groups/{id}"; public const string constMsGraphGroupMembers = "groups/{id}/members"; public const string constMsGraphGroupMembersAdd = "groups/{id}/members/$ref"; public const string constMsGraphGroupMembersDelete = "groups/{id}/members/{memberId}/$ref"; public const string constMsGraphGroupOwnersAdd = "groups/{id}/owners/$ref"; public const string constMsGraphGroupOwnersDelete = "groups/{id}/owners/{memberId}/$ref"; public const string constMsGraphGroupTransitiveMembers = "groups/{id}/transitiveMembers"; public const string constMsGraphGroupOwners = "groups/{id}/owners"; public const string constMsGraphGroupDrive = "groups/{id}/drive"; public const string constMsGraphDriveInfo = "drives/{id}"; public const string constMsGraphDriveRoot = "drives/{id}/root"; public const string constMsGraphFileObjectInfo = "drives/{driveId}/items/{id}"; public const string constMsGraphFileObjectChildren = "drives/{driveId}/items/{itemId}/children/?$select=id,name,file"; public const string constMsGraphFileObjectByName = "drives/{driveId}/items/{itemId}/children/?$select=id,name,file&$filter=name eq '{name}'"; public const string constMsGraphFileObjectPermissions = "/drives/{driveId}/items/{id}/permissions"; public const string constMsGraphTeamChannelList = "teams/{id}/channels"; public const string constMsGraphTeamClone = "teams/{id}/clone"; public const string constMsGraphTeamPrivateChannelList = "teams/{id}/channels?$filter=membershipType eq 'private'"; public const string constMsGraphTeamChannelInfo = "teams/{groupId}/channels/{id}"; public const string constMsGraphTeamChannelRoot = "teams/{groupId}/channels/{id}/filesFolder"; public const string constMsGraphTeamFileObjectPermissionInvite = "drives/{driveId}/items/{id}/invite"; public const string constMsGraphTeamFileObjectPermissionDelete = "drives/{driveId}/items/{itemId}/permissions/{id}"; public const string constMsGraphTeamFileObjectPermissionRevokeGrant = "drives/{driveId}/items/{itemId}/permissions/{id}/revokeGrants"; public const string constMsGraphUserInfo = "users/{email}"; public cMsGraphBase Base { get; private set; } = null; public bool IsOnline { get { if (Base == null) return false; return Base.IsOnline; } } public cMsGraphSharepoint(cMsGraphBase Base) { this.Base = Base; } public async Task RequestTeamsListAsync() { Base.ResetError(); try { var Result = await Base.RequestListAsync(constMsGraphTeamsList, UseBeta: true, retryForbidden: true); if (Result != null) { var RetVal = new cMsGraphCollectionGroups(Result.Count); foreach (var Entry in Result) { var res = new cMsGraphResultGroup(Entry); RetVal.Add(res); } return RetVal; } } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestGroupInfoAsync(string ID) { Base.ResetError(); try { var strRequest = constMsGraphGroupInfo.Replace("{id}", ID); var Result = await Base.RequestAsync(strRequest); if (Result != null) return new cMsGraphResultGroup(Result); } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task CloneTeam(string ID, CloneTeamRequest cloneTeamRequest) { Base.ResetError(); try { var strRequest = constMsGraphTeamClone.Replace("{id}", ID); var Result = await Base.RequestAsync(strRequest, false, cMsGraphBase.eHttpMethod.post, cloneTeamRequest); var Result2 = await GetOperationResult(Result.Result); //Base.RequestAsync(Result.Result, false, cMsGraphBase.eHttpMethod.get); if (Result2 != null) return Result2; } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task GetOperationResult(string operationUrl) { Base.ResetError(); const int maxAttempts = 5; const int delaySeconds = 30; for (int attempt = 1; attempt <= maxAttempts; attempt++) { try { var result = await Base.RequestAsync(operationUrl, false, cMsGraphBase.eHttpMethod.get); if (result == null) continue; switch (result.Result.status.ToLowerInvariant()) { case "notstarted": case "inprogress": if (attempt == maxAttempts) { cLogManager.LogEntry($"Maximale Anzahl Versuche erreicht ({maxAttempts}). Operation noch nicht abgeschlossen.", LogLevels.Error); return result; } await Task.Delay(TimeSpan.FromSeconds(delaySeconds)); break; case "failed": cLogManager.LogEntry($"Operation failed: {result.Result.error?.ToString() ?? "Unknown error"}", LogLevels.Error); return result; case "succeeded": return result; default: cLogManager.LogEntry($"Unexpected operation status: {result.Result.status}", LogLevels.Warning); return result; } } catch (Exception ex) { cLogManager.LogException(ex); return null; } } cLogManager.LogEntry($"Operation nicht abgeschlossen nach {maxAttempts} Versuchen.", LogLevels.Error); return null; } public async Task RequestUserInfoAsync(string email) { Base.ResetError(); try { var strRequest = constMsGraphUserInfo.Replace("{email}", email); var Result = await Base.RequestAsync(strRequest); if (Result != null) return new cMsGraphResultUser(Result); } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestGroupMembersAsync(string GroupID, string UserId = null) { return await privRequestGroupMembersAsync(constMsGraphGroupMembers, GroupID, UserId); } public async Task RequestGroupTransitiveMembers(string GroupID, string UserId = null) { return await privRequestGroupMembersAsync(constMsGraphGroupTransitiveMembers, GroupID, UserId); } public async Task RequestGroupOwnersAsync(string GroupID, string UserId = null) { return await privRequestGroupMembersAsync(constMsGraphGroupOwners, GroupID, UserId); } private async Task privRequestGroupMembersAsync(string Url, string GroupID, string UserId) { Base.ResetError(); try { var Url2 = Url.Replace("{id}", GroupID); if (!string.IsNullOrEmpty(UserId)) Url2 += $"/?$filter=id eq '{UserId}'"; var Result = await Base.RequestListAsync(Url2); if (Result != null) { var RetVal = new cMsGraphCollectionUsers(Result.Count); foreach (var Entry in Result) { var res = new cMsGraphResultUser(Entry); if (!string.IsNullOrEmpty(res.UserPrincipalName)) RetVal.Add(res); } return RetVal; } } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestGroupDrive(string GroupID) { Base.ResetError(); try { var strRequest = constMsGraphGroupDrive.Replace("{id}", GroupID); var Result = await Base.RequestAsync(strRequest); if (Result != null) return new cMsGraphResultDrive(Result); } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestDriveInfo(string DriveID) { Base.ResetError(); try { var strRequest = constMsGraphDriveInfo.Replace("{id}", DriveID); var Result = await Base.RequestAsync(strRequest); if (Result != null) { var RetVal = new cMsGraphResultDrive(Result); return RetVal; } } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestDriveRoot(cMsGraphResultDrive Drive) { Base.ResetError(); try { var strRequest = constMsGraphDriveRoot.Replace("{id}",Drive.ID); var Result = await Base.RequestAsync(strRequest); if (Result != null) return new cMsGraphResultFileObject(Drive.ID, Result, Drive); } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestFileObjectInfo(string DriveID, string ID, cMsGraphResultDrive Drive = null) { Base.ResetError(); try { var strRequest = constMsGraphFileObjectInfo.Replace("{driveId}", DriveID).Replace("{id}", ID); var Result = await Base.RequestAsync(strRequest); if (Result != null) { var RetVal = new cMsGraphResultFileObject(DriveID, Result, Drive); return RetVal; } } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestFileObjectByName(cMsGraphResultFileObject Folder, string Name) { Base.ResetError(); if (Folder == null || Folder.DriveID == null) return null; try { var strName = HttpUtility.UrlEncode(Name); var strRequest = constMsGraphFileObjectByName.Replace("{driveId}", Folder.DriveID); strRequest = strRequest.Replace("{itemId}", Folder.ID); strRequest = strRequest.Replace("{name}", strName); var Result = await Base.RequestAsync(strRequest); if (Result != null) { if (Result.Result.value.Count >= 1) { dynamic d = Result.Result.value[0]; var f = new cMsGraphResultBase(d); return new cMsGraphResultFileObject(Folder.DriveID, f, Folder.Drive); } } } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestFileObjectSubitems(string DriveID, string ID, bool Folders, cMsGraphResultDrive Drive = null) { Base.ResetError(); try { var strRequest = constMsGraphFileObjectChildren.Replace("{driveId}", DriveID).Replace("{itemId}", ID); var Result = await Base.RequestListAsync(strRequest); if (Result != null) { var RetVal = new cMsGraphCollectionFileObjects(); foreach (var Entry in Result) { var item = new cMsGraphResultFileObject(DriveID, Entry, Drive); if (item.IsFolder ^ !Folders) RetVal.Add(item); } return RetVal; } } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestFileObjectPermissions(cMsGraphResultFileObject Item) { Base.ResetError(); try { if (Item.DriveID == null) return null; var strRequest = constMsGraphFileObjectPermissions.Replace("{driveId}", Item.DriveID).Replace("{id}", Item.ID); var Result = await Base.RequestListAsync(strRequest); if (Result != null) { var RetVal = new cMsGraphCollectionPermissions(); foreach (var Entry in Result) { var item = cMsGraphResultPermission.CreateInstance(Item, Entry); if (item != null) RetVal.Add(item); } return RetVal; } } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestTeamChannels(cMsGraphResultGroup Team, bool OnlyPrivate = false) { Base.ResetError(); try { var strUrl = constMsGraphTeamChannelList; if (OnlyPrivate) strUrl = constMsGraphTeamPrivateChannelList; var strRequest = strUrl.Replace("{id}", Team.ID); var Result = await Base.RequestListAsync(strRequest, retryForbidden: true); if (Result != null) { var RetVal = new cMsGraphCollectionChannels(Result.Count); foreach (var Entry in Result) { var item = new cMsGraphResultChannel(Team.ID, Entry, Team); RetVal.Add(item); } return RetVal; } else { } } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestChannelInfo(string TeamsID, string ChannelID, cMsGraphResultGroup Team = null) { Base.ResetError(); try { var strRequest = constMsGraphTeamChannelInfo.Replace("{groupId}", TeamsID).Replace("{id}", ChannelID); var Result = await Base.RequestAsync(strRequest); if (Result != null) { var RetVal = new cMsGraphResultChannel(TeamsID, Result, Team); return RetVal; } } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RequestChannelRoot(cMsGraphResultChannel Channel) { Base.ResetError(); try { var strRequest = constMsGraphTeamChannelRoot.Replace("{groupId}", Channel.TeamID).Replace("{id}", Channel.ID); var Result = await Base.RequestAsync(strRequest, retryForbidden: true); if (Result != null) { var RetVal = new cMsGraphResultChannelRoot(Channel, Result); return RetVal; } } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task AddGroupMembership(cMsGraphResultGroup group, bool owner, cMsGraphResultUser user) { Base.ResetError(); try { string strRequest; if (owner) strRequest = constMsGraphGroupOwnersAdd; else strRequest = constMsGraphGroupMembersAdd; strRequest= strRequest.Replace("{id}", group.ID); var Request = new AddGroupMemberRequest() { oDataId = user.ODataId }; var Result = await Base.RequestAsync(strRequest, httpMethod: cMsGraphBase.eHttpMethod.post, JsonData: Request); if (Result == null) return false; } catch (Exception E) { cLogManager.LogException(E); } return false; } public async Task DeleteGroupMembership(cMsGraphResultGroup group, bool owner, cMsGraphResultUser user) { Base.ResetError(); try { string strRequest; if (owner) strRequest = constMsGraphGroupOwnersDelete; else strRequest = constMsGraphGroupMembersDelete; strRequest = strRequest.Replace("{id}", group.ID).Replace("{memberId}", user.ID); var Result = await Base.RequestAsync(strRequest, httpMethod: cMsGraphBase.eHttpMethod.delete); if (Result == null) return false; } catch (Exception E) { cLogManager.LogException(E); } return false; } public async Task> AddFileObjectPermission(cMsGraphResultFileObject Item, IEnumerable Roles, cMsGraphResultPermission.eDriveReceipientType RecipientType, string RecipientID, bool RequireSignIn = true, bool SendInvitation = false, string Message = null) { Base.ResetError(); try { if (Item?.ID == null) return null; if (Item?.DriveID == null) return null; var Recipient = DriveRecipient.Create(RecipientType, RecipientID); var Recipients = new List() { Recipient }; var roles = new List(); foreach (var R in Roles) roles.Add(R.ToString()); if (!SendInvitation) RequireSignIn = true; var Request = new AddPermissionRequest() { requireSignIn = RequireSignIn, sendInvitation = SendInvitation, message = Message, recipients = Recipients, roles = roles }; var strRequest = constMsGraphTeamFileObjectPermissionInvite.Replace("{driveId}", Item.DriveID).Replace("{id}", Item.ID); var Result = await Base.RequestAsync(strRequest, httpMethod: cMsGraphBase.eHttpMethod.post, JsonData: Request); if (Result == null) return null; if (!Result.Result.TryGetValue("value", out JToken Value)) return null; if (Result.Result.value.Count <= 0) return null; var RetVal = new List(); foreach (dynamic Entry in Result.Result.value) { var Entry2 = new cMsGraphResultBase(Entry); var Perm = cMsGraphResultPermission.CreateInstance(Item, Entry2); RetVal.Add(Perm); } return RetVal; } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task DeleteFileObjectPermission(cMsGraphResultPermission Permission) { Base.ResetError(); try { if (Permission?.ID == null) return false; if (Permission?.Item?.ID == null) return false; if (Permission?.Item?.DriveID == null) return false; var strRequest = constMsGraphTeamFileObjectPermissionDelete.Replace("{driveId}", Permission.Item.DriveID).Replace("{itemId}", Permission.Item.ID).Replace("{id}", Permission.ID); var Result = await Base.RequestAsync(strRequest, httpMethod: cMsGraphBase.eHttpMethod.delete); if (Result != null) return true; } catch (Exception E) { cLogManager.LogException(E); } return false; } public async Task RevokeFileObjectPermissionGrant(cMsGraphResultPermission Permission, cMsGraphResultPermission.eDriveReceipientType RecipientType, string RecipientID) { Base.ResetError(); try { if (Permission?.ID == null) return null; if (Permission?.Item?.ID == null) return null; if (Permission?.Item?.DriveID == null) return null; var strRequest = constMsGraphTeamFileObjectPermissionRevokeGrant.Replace("{driveId}", Permission.Item.DriveID).Replace("{itemId}", Permission.Item.ID).Replace("{id}", Permission.ID); var Recipient = DriveRecipient.Create(RecipientType, RecipientID); var Grantees = new List() { Recipient }; var RequestData = new RevokeGrantRequest() { grantees = Grantees }; var Result = await Base.RequestAsync(strRequest, UseBeta: true, httpMethod: cMsGraphBase.eHttpMethod.post, JsonData: RequestData); if (Result != null) { var RetVal = new cMsGraphResultPermission(Permission.Item, Result); return RetVal; } } catch (Exception E) { cLogManager.LogException(E); } return null; } public class CloneTeamRequest { [JsonConverter(typeof(StringEnumConverter))] public enum TeamVisibilityType { [JsonProperty("private")] Private = 0, [JsonProperty("public")] Public = 1, [JsonProperty("hiddenMembership")] HiddenMembership = 2 } [Flags] public enum ClonableTeamParts { None = 0, [JsonProperty("apps")] Apps = 1, [JsonProperty("tabs")] Tabs = 2, [JsonProperty("settings")] Settings = 4, [JsonProperty("channels")] Channels = 8, [JsonProperty("members")] Members = 16 } [JsonProperty("displayName", NullValueHandling = NullValueHandling.Ignore)] public string DisplayName { get; set; } [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] public string Description { get; set; } [JsonProperty("mailNickname", NullValueHandling = NullValueHandling.Ignore)] public string MailNickname { get; set; } [JsonProperty("partsToClone", NullValueHandling = NullValueHandling.Ignore)] public string PartsToClone { get; set; } [JsonProperty("visibility")] [JsonConverter(typeof(StringEnumConverter))] public TeamVisibilityType Visibility { get; set; } public void SetClonableParts(ClonableTeamParts parts) { var partList = new System.Collections.Generic.List(); if (parts.HasFlag(ClonableTeamParts.Apps)) partList.Add("apps"); if (parts.HasFlag(ClonableTeamParts.Tabs)) partList.Add("tabs"); if (parts.HasFlag(ClonableTeamParts.Settings)) partList.Add("settings"); if (parts.HasFlag(ClonableTeamParts.Channels)) partList.Add("channels"); if (parts.HasFlag(ClonableTeamParts.Members)) partList.Add("members"); PartsToClone = string.Join(",", partList); } } private class AddPermissionRequest { public bool requireSignIn { get; set; } public bool sendInvitation { get; set; } public string message { get; set; } public IEnumerable roles { get; set; } public IEnumerable recipients { get; set; } } private class AddGroupMemberRequest { [JsonProperty("@odata.id")] public string oDataId { get; set; } } private class DriveRecipient { public string email { get; set; } public string alias { get; set; } public string objectId { get; set; } public static DriveRecipient Create(cMsGraphResultPermission.eDriveReceipientType RecipientType, string RecipientID) { var Recipient = new DriveRecipient(); switch (RecipientType) { case cMsGraphResultPermission.eDriveReceipientType.objectId: Recipient.objectId = RecipientID; break; case cMsGraphResultPermission.eDriveReceipientType.alias: Recipient.email = RecipientID; break; default: Recipient.email = RecipientID; break; } return Recipient; } } private class RevokeGrantRequest { public IEnumerable grantees { get; set; } } } public class cMsGraphResultGroup : cMsGraphResultBase { public string Description { get; private set; } = null; public string SID { get; private set; } = null; public string Visibility { get; private set; } = null; public string MailEnabled { get; private set; } = null; public string MailAddress { get; private set; } = null; public cMsGraphResultDrive Drive { get; private set; } = null; public cMsGraphCollectionChannels Channels { get; private set; } = null; public cMsGraphResultGroup(cMsGraphResultBase Result) : base(Result) { try { Description = Result.Result.description; } catch { }; try { SID = Result.Result.securityIdentifier; } catch { }; try { Visibility = Result.Result.visibility; } catch { }; try { MailEnabled = Result.Result.mailEnabled; } catch { }; try { MailAddress = Result.Result.mail; } catch { }; } public async Task AddMember() { await Task.Delay(0); return false; } public async Task ResolveDrive(cMsGraphSharepoint SP) { Drive = await SP.RequestGroupDrive(ID); return Drive != null; } public async Task ResolveChannels(cMsGraphSharepoint SP, bool OnlyPrivate = false) { Channels = await SP.RequestTeamChannels(this, OnlyPrivate); return Channels != null; } public async Task GetMembersAsync(cMsGraphSharepoint SP) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { var RetVal = await SP.RequestGroupMembersAsync(this.ID); return RetVal; } catch (Exception E) { LogException(E); return null; } finally { LogMethodEnd(CM); } } public async Task GetOwnersAsync(cMsGraphSharepoint SP) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { var RetVal = await SP.RequestGroupOwnersAsync(this.ID); return RetVal; } catch (Exception E) { LogException(E); return null; } finally { LogMethodEnd(CM); } } } public class cMsGraphCollectionGroups : SortedList { public cMsGraphCollectionGroups() {} public cMsGraphCollectionGroups(int n) : base(n) { } public void Add(cMsGraphResultGroup Group) { if (!string.IsNullOrEmpty(Group.DisplayName)) if (!this.ContainsKey(Group.DisplayName)) this.Add(Group.DisplayName, Group.ID); } } public class cMsGraphResultChannel : cMsGraphResultBase { public string Description { get; private set; } = null; public string IsFavoriteByDefault { get; private set; } = null; public string MembershipType { get; private set; } = null; public string MailAddress { get; private set; } = null; public string TeamID { get; private set; } = null; public cMsGraphResultGroup Team { get; private set; } = null; public cMsGraphResultFileObject RootFolder { get; private set; } = null; public bool RootFolderResolved { get; private set; } = false; public cMsGraphResultChannel(string TeamID, cMsGraphResultBase Result, cMsGraphResultGroup Team = null) : base(Result) { this.TeamID = TeamID; this.Team = Team; try { Description = Result.Result.description; } catch { }; try { IsFavoriteByDefault = Result.Result.isFavoriteByDefault; } catch { }; try { MembershipType = Result.Result.membershipType; } catch { }; try { MailAddress = Result.Result.mail; } catch { }; } public async Task ResolveRootFolder(cMsGraphSharepoint SP) { if (Team == null) { Team = await SP.RequestGroupInfoAsync(TeamID); if (Team == null) return false; } RootFolderResolved = true; if (Team.Drive == null) if (!await Team.ResolveDrive(SP)) return false; if (Team.Drive.Root == null) if (!await Team.Drive.ResolveRoot(SP)) return false; var RF = await SP.RequestChannelRoot(this); if (RF != null) if (!string.IsNullOrEmpty(RF.DriveID)) { cMsGraphResultDrive dr = null; if ((Team.Drive != null) && (Team.Drive.ID == RF.DriveID)) dr = Team.Drive; else if (await RF.ResolveDrive(SP)) dr = RF.Drive; if (dr != null) RootFolder = await SP.RequestFileObjectInfo(dr.ID, RF.ID, dr); } return RootFolder != null; } } public class cMsGraphCollectionChannels : SortedList { public cMsGraphCollectionChannels() { } public cMsGraphCollectionChannels(int n) : base(n) { } public void Add(cMsGraphResultChannel Channel) { if (!this.ContainsKey(Channel.DisplayName)) this.Add(Channel.DisplayName, Channel); } } public class cMsGraphResultDrive : cMsGraphResultBase { public string DriveType { get; private set; } = null; public cMsGraphResultFileObject Root { get; private set; } = null; public cMsGraphResultDrive(cMsGraphResultBase Result) : base(Result) { try { DriveType = Result.Result.driveType; } catch { }; } public async Task ResolveRoot(cMsGraphSharepoint SP) { Root = await SP.RequestDriveRoot(this); return Root != null; } } public class cMsGraphResultPermission : cMsGraphResultBase { public enum eDriveReceipientType { email, alias, objectId}; public enum ePermissionRole { owner, read, write }; static public ePermissionRole getRole(string s) { switch (s.ToLowerInvariant()) { case "owner": return ePermissionRole.owner; case "write": return ePermissionRole.write; default: return ePermissionRole.read; } } public cMsGraphResultFileObject Item { get; private set; } = null; public List Identities { get; private set; } = new List(); public List Roles { get; private set; } = new List(); public bool isInherited { get; private set; } = false; public cMsGraphResultPermission(cMsGraphResultFileObject Item, cMsGraphResultBase Result) : base(Result) { try { this.Item = Item; if (Result.Result.TryGetValue("roles", out JToken JT1)) { Roles = new List(Result.Result.roles.Count); foreach (dynamic Entry in Result.Result.roles) Roles.Add(getRole( Entry.ToString())); } if (Result.Result.TryGetValue("inheritedFrom", out JToken JT)) { isInherited = true; } } catch (Exception E) { cLogManager.LogException(E); } } static public cMsGraphResultPermission CreateInstance(cMsGraphResultFileObject Item, cMsGraphResultBase Result) { if (PermissionDirect.Check(Result.Result)) return new PermissionDirect(Item, Result); if (PermissionLink.Check(Result.Result)) return new PermissionLink(Item, Result); return new cMsGraphResultPermission(Item, Result); } public async Task Delete(cMsGraphSharepoint SP) { try { var RetVal = await SP.DeleteFileObjectPermission(this); return RetVal; } catch (Exception E) { cLogManager.LogException(E); } return false; } public async Task RevokeGrant(cMsGraphSharepoint SP, cMsGraphResultPermission.eDriveReceipientType RecipientType, string RecipientID) { try { if (this is cMsGraphResultPermission.PermissionDirect) { var RetVal = await SP.DeleteFileObjectPermission(this); return RetVal; } else if (this is cMsGraphResultPermission.PermissionLink) { var RetVal = await SP.RevokeFileObjectPermissionGrant(this, RecipientType, RecipientID); if (RetVal != null) return true; } } catch (Exception E) { cLogManager.LogException(E); } return false; } public class PermissionDirect : cMsGraphResultPermission { public PermissionDirect(cMsGraphResultFileObject Item, cMsGraphResultBase Result) : base(Item, Result) { try { if (Result.Result.TryGetValue("grantedTo", out JToken JT1)) { var Identity = new cMsGraphPermissionIdentity(Result.Result.grantedTo); Identities.Clear(); Identities.Add(Identity); } } catch (Exception E) { cLogManager.LogException(E); } } public static bool Check(dynamic Result) { try { if (Result.TryGetValue("grantedTo", out JToken JT1)) if (Result.grantedTo.TryGetValue("user", out JToken JT2)) return true; } catch (Exception E) { cLogManager.LogException(E); } return false; } } public class PermissionLink : cMsGraphResultPermission { public string Scope { get; private set; } = null; public string Type { get; private set; } = null; public string PreventsDownload { get; private set; } = null; public string WebUrl { get; private set; } = null; public PermissionLink(cMsGraphResultFileObject Item, cMsGraphResultBase Result) : base(Item, Result) { try { if (Result.Result.TryGetValue("link", out JToken JT1)) { dynamic lnk = Result.Result.link; if (lnk.TryGetValue("type", out JToken JT2)) Type = lnk.type; if (lnk.TryGetValue("scope", out JToken JT3)) Scope = lnk.scope; if (lnk.TryGetValue("preventsDownload", out JToken JT4)) PreventsDownload = lnk.preventsDownload; if (lnk.TryGetValue("webUrl", out JToken JT5)) WebUrl = lnk.webUrl; } if (Result.Result.TryGetValue("grantedToIdentities", out JToken JT6)) { Identities.Clear(); foreach (dynamic Entry in Result.Result.grantedToIdentities) { try { var Ident = new cMsGraphPermissionIdentity(Entry); if (Ident != null) Identities.Add(Ident); } catch (Exception E) { cLogManager.LogException(E); } } } } catch (Exception E) { cLogManager.LogException(E); } } public static bool Check(dynamic Result) { try { if (Result.TryGetValue("link", out JToken JT1)) return true; } catch (Exception E) { cLogManager.LogException(E); } return false; } } public class cMsGraphPermissionIdentity { public enum eIdentityType { unknown = 0, user, device, application, }; public eIdentityType IdentityType { get; private set; } = eIdentityType.unknown; public string ID { get; private set; } = null; public string EMail { get; private set; } = null; public string DisplayName { get; private set; } = null; public cMsGraphPermissionIdentity(dynamic Result) { try { dynamic ident = null; if (Result.TryGetValue("user", out JToken JT1)) { ident = Result.user; IdentityType = eIdentityType.user; } else if (Result.TryGetValue("device", out JToken JT2)) { ident = Result.device; IdentityType = eIdentityType.device; } else if (Result.TryGetValue("application", out JToken JT3)) { ident = Result.application; IdentityType = eIdentityType.application; } if (ident != null) if (ident.TryGetValue("displayName", out JToken JT3)) DisplayName = ident.displayName; if (ident.TryGetValue("id", out JToken JT4)) ID = ident.id; if (ident.TryGetValue("email", out JToken JT5)) EMail = ident.email; } catch (Exception E) { cLogManager.LogException(E); } } } } public class cMsGraphCollectionPermissions : List { public cMsGraphCollectionPermissions() { } public cMsGraphCollectionPermissions(int n) : base(n) { } } public class cMsGraphResultFileObject : cMsGraphResultBase { public readonly string DriveID = null; public readonly cMsGraphResultDrive Drive = null; public bool IsFolder { get; private set; } = false; public string WebUrl { get; private set; } = null; public cMsGraphCollectionFileObjects Folders { get; private set; } = null; public cMsGraphCollectionFileObjects Files { get; private set; } = null; public cMsGraphCollectionPermissions Permissions { get; private set; } = null; public cMsGraphResultFileObject(string DriveID, cMsGraphResultBase Result, cMsGraphResultDrive Drive = null) : base(Result) { this.DriveID = DriveID; this.Drive = Drive; try { IsFolder = !Result.Result.TryGetValue("file", out JToken JT1); WebUrl = cMsGraphResultBase.GetStringFromDynamic(Result.Result, "webUrl"); } catch { } } public async Task ResolveFolders(cMsGraphSharepoint SP) { Folders = await SP.RequestFileObjectSubitems(this.DriveID, this.ID, true, this.Drive); return Folders != null; } public async Task ResolveFiles(cMsGraphSharepoint SP) { Files = await SP.RequestFileObjectSubitems(this.DriveID, this.ID, true, this.Drive); return Files != null; } public async Task ResolvePermissions(cMsGraphSharepoint SP) { Permissions = await SP.RequestFileObjectPermissions(this); return Permissions != null; } public async Task> AddPermission(cMsGraphSharepoint SP, IEnumerable Roles, cMsGraphResultPermission.eDriveReceipientType ReceipientType , string RecipientID, bool RequireSignIn = true, bool SendInvitation = false, string Message = null) { try { var RetVal = await SP.AddFileObjectPermission(this, Roles, ReceipientType, RecipientID, RequireSignIn, SendInvitation, Message); return RetVal; } catch (Exception E) { cLogManager.LogException(E); } return null; } public async Task RemovePermission(cMsGraphSharepoint SP, cMsGraphResultPermission.ePermissionRole Role, string RecipientID) { try { var RetVal = await ResolvePermissions(SP); if (!RetVal || Permissions == null) return true; var Found = false; foreach (var Entry in Permissions) { if (Entry.Identities == null || Entry.Roles == null) continue; if (!Entry.Roles.Contains(Role)) continue; foreach (var Identity in Entry.Identities) { var Revoked = false; if (Identity.ID == RecipientID) Revoked = await Entry.RevokeGrant(SP, cMsGraphResultPermission.eDriveReceipientType.objectId, RecipientID); else if (Identity.EMail?.ToUpperInvariant() == RecipientID.ToUpperInvariant()) Revoked = await Entry.RevokeGrant(SP, cMsGraphResultPermission.eDriveReceipientType.email, RecipientID); Found |= Revoked; } } return Found; } catch (Exception E) { cLogManager.LogException(E); } return false; } } public class cMsGraphCollectionFileObjects : Dictionary { public cMsGraphCollectionFileObjects() { } public cMsGraphCollectionFileObjects(int n) : base(n) { } public void Add(cMsGraphResultFileObject FileObject) { if (!this.ContainsKey(FileObject.ID)) this.Add(FileObject.ID, FileObject); } } public class cMsGraphResultChannelRoot : cMsGraphResultBase { public cMsGraphResultChannel Channel { get; private set; } = null; public cMsGraphResultDrive Drive { get; private set; } = null; public string DriveID { get; private set; } = null; public cMsGraphResultChannelRoot(cMsGraphResultChannel Channel, cMsGraphResultBase Result) : base(Result) { this.Channel = Channel; try { if (Result.Result.TryGetValue("parentReference", out JToken JT1)) { var pR = Result.Result.parentReference; if (pR.TryGetValue("driveId", out JToken JT2)) { DriveID = pR.driveId; } } } catch { } } public async Task ResolveDrive(cMsGraphSharepoint SP) { if (string.IsNullOrEmpty(DriveID)) return false; Drive = await SP.RequestDriveInfo(DriveID); return Drive != null; } } }