using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Graph; using Microsoft.Identity.Client; using Microsoft.Graph.Models; using Microsoft.Kiota.Abstractions.Authentication; using System.ComponentModel.Design; using log4net; using System.Threading; namespace Epi2Exchange2 { internal class O365Connector { private static readonly ILog Logger = LogManager.GetLogger(typeof(O365Connector)); private string clientID; private string clientSecret; private string tenantID; private string BaseUrl; public O365Connector(string clientID, string clientSecret, string tenantID, string BaseUrl) { this.clientID = clientID; this.clientSecret = clientSecret; this.tenantID = tenantID; this.BaseUrl = BaseUrl; } public async Task SyncContact(Contact contact, string destinationAccountPrimaryAddress) { try { var graphClient = await GetGraphClient(); if (await DoesContactExist(contact, destinationAccountPrimaryAddress, graphClient)) { Logger.Info("Contact " + contact.DisplayName + " found in O365"); string O365ContactID = await GetContactIdByNickName(graphClient, destinationAccountPrimaryAddress, contact.NickName); if (!string.IsNullOrEmpty(O365ContactID)) { await graphClient.Users[destinationAccountPrimaryAddress] .Contacts[O365ContactID] .PatchAsync(contact); Logger.Info($"Contact with ID '{O365ContactID}' successfully updated."); } else { Logger.Warn("No valid contact ID found for update."); } } else { Logger.Info("Contact " + contact.DisplayName + " NOT found in O365"); Logger.Info("Creating new Contact"); await graphClient.Users[destinationAccountPrimaryAddress].Contacts.PostAsync(contact); } } catch (Exception ex) { Logger.Error("Error while synchronizing contact: " + ex.Message); } } private async Task GetContactIdByNickName(GraphServiceClient graphClient, string userPrimaryMail, string nickName) { try { var contacts = await graphClient.Users[userPrimaryMail] .Contacts .GetAsync(requestConfiguration => { requestConfiguration.QueryParameters.Filter = $"NickName eq '{nickName}'"; }); var contact = contacts?.Value?.FirstOrDefault(); return contact?.Id; } catch (Exception ex) { Logger.Error($"Error retrieving contact with NickName '{nickName}': {ex.Message}"); return null; } } private async Task GetGraphClient() { try { var clientApp = ConfidentialClientApplicationBuilder.Create(clientID) .WithClientSecret(clientSecret) .WithAuthority(new Uri($"{BaseUrl}/{tenantID}")) .Build(); var accessTokenProvider = new TokenAcquisitionProvider(clientApp); var authProvider = new BaseBearerTokenAuthenticationProvider(accessTokenProvider); return new GraphServiceClient(authProvider); } catch (Exception ex) { Logger.Error("Error initializing GraphServiceClient: " + ex.Message); throw; } } private async Task DoesContactExist(Contact contact, string userPrimaryMail, GraphServiceClient graphClient) { string NickName = contact.NickName; if (string.IsNullOrWhiteSpace(NickName)) { Logger.Warn("No valid NickName found for the given contact."); return false; } try { var contacts = await graphClient.Users[userPrimaryMail] .Contacts .GetAsync(requestConfiguration => { requestConfiguration.QueryParameters.Filter = $"NickName eq '{NickName}'"; }); bool exists = contacts?.Value != null && contacts.Value.Any(); Logger.Info($"Contact with NickName '{NickName}' exists: {exists}"); return exists; } catch (Exception ex) { Logger.Error($"Error checking contacts: {ex.Message}"); return false; } } } public class TokenAcquisitionProvider : IAccessTokenProvider { private readonly IConfidentialClientApplication _clientApp; public TokenAcquisitionProvider(IConfidentialClientApplication clientApp) { _clientApp = clientApp; } public async Task GetAuthorizationTokenAsync(Uri uri, Dictionary additionalAuthenticationContext = default, CancellationToken cancellationToken = default) { try { var result = await _clientApp.AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" }) .ExecuteAsync(cancellationToken); return result.AccessToken; } catch (Exception ex) { Logger.Error("Error acquiring token: " + ex.Message); throw; } } public AllowedHostsValidator AllowedHostsValidator { get; } = new AllowedHostsValidator(); } }