/// <summary> /// Set the meeting acceptance status, in CRM, for this invitee to this meeting from /// their acceptance status in Outlook. /// </summary> /// <param name="meeting">The appointment item representing the meeting</param> /// <param name="invitee">The recipient item representing the invitee</param> /// <param name="acceptance">The acceptance status of this invitee of this meeting /// as a string recognised by CRM.</param> /// private int AddOrUpdateMeetingAcceptanceFromOutlookToCRM(Outlook.AppointmentItem meeting, Outlook.Recipient invitee, string acceptance) { int count = 0; string smtpAddress = invitee.GetSmtpAddress(); var meetingId = meeting.GetCrmId(); if (meetingId != null && !string.IsNullOrEmpty(acceptance) && SyncDirection.AllowOutbound(this.Direction)) { foreach (AddressResolutionData resolution in this.ResolveRecipient(meeting, invitee)) { try { RestAPIWrapper.SetMeetingAcceptance(meetingId.ToString(), resolution.ModuleName, resolution.ModuleId.ToString(), acceptance); count++; } catch (System.Exception any) { ErrorHandler.Handle($"Failed to resolve meeting invitee {smtpAddress}:", any); } } } return(count); }
/// <summary> /// True if we should despatch this item to CRM, else false. /// </summary> /// <param name="olItem"></param> /// <returns>true iff settings.SyncCalendar is true, the item is not null, and it is not private (normal sensitivity)</returns> private bool ShouldDespatchToCrm(Outlook.AppointmentItem olItem) { var syncConfigured = SyncDirection.AllowOutbound(Properties.Settings.Default.SyncCalendar); return(olItem != null && syncConfigured && olItem.Sensitivity == Outlook.OlSensitivity.olNormal); }
/// <summary> /// Does the currently cached value allow access to this module name in this direction? /// </summary> /// <param name="moduleName"></param> /// <param name="direction"></param> /// <returns>True if access is permitted, false if it's denied, null if there's no /// cached value.</returns> private bool?HasCachedAccess(string moduleName, string direction) { bool?result = null; if (this.crmImportExportPermissionsCache.ContainsKey(moduleName)) { SyncDirection.Direction cachedValue = this.crmImportExportPermissionsCache[moduleName]; result = (direction == ImportPermissionToken && SyncDirection.AllowOutbound(cachedValue)) || (direction == ExportPermissionToken && SyncDirection.AllowInbound(cachedValue)); } return(result); }
/// <summary> /// Perform all the necessary checking before adding or updating an item on CRM. /// </summary> /// <remarks> /// TODO TODO TODO: This does NOT actually do all the checking. Checking is also /// done in SyncState.ShouldSyncWithCRM, and possibly other places. Fix. /// </remarks> /// <param name="item">The item we may seek to add or update.</param> /// <param name="crmType">The CRM type of that item.</param> /// <returns>true if we may attempt to add or update that item.</returns> protected bool ShouldAddOrUpdateItemFromOutlookToCrm(OutlookItemType item, string crmType) { bool result; string prefix = "Synchoniser.ShouldAddOrUpdateItemFromOutlookToCrm"; try { if (item == null) { Log.Warn($"{prefix}: attempt to send null {crmType}?"); result = false; } else { if (SyncDirection.AllowOutbound(Direction)) { if (this.permissionsCache.HasImportAccess(crmType)) { if (this.GetSensitivity(item) == Outlook.OlSensitivity.olNormal) { result = true; } else { Log.Info($"{prefix}: {crmType} not added to CRM because its sensitivity is not public."); result = false; } } else { Log.Info($"{prefix}: {crmType} not added to CRM because import access is not granted."); result = false; } } else { Log.Info($"{prefix}: {crmType} not added to CRM because synchronisation is not enabled."); result = false; } } } catch (Exception any) { Log.Error($"{prefix}: unexpected failure while checking {crmType}.", any); result = false; } return(result); }
/// <summary> /// Remove the item implied by this sync state from CRM. /// </summary> /// <param name="state">A sync state wrapping an item which has been deleted or marked private in Outlook.</param> protected virtual void RemoveFromCrm(SyncState state) { if (SyncDirection.AllowOutbound(Direction)) { var crmEntryId = state.CrmEntryId; if (state.ExistedInCrm && this.permissionsCache.HasImportAccess(state.CrmType)) { eNameValue[] data = new eNameValue[2]; data[0] = clsSuiteCRMHelper.SetNameValuePair("id", crmEntryId); data[1] = clsSuiteCRMHelper.SetNameValuePair("deleted", "1"); clsSuiteCRMHelper.SetEntryUnsafe(data, state.CrmType); } state.RemoveCrmLink(); } }
/// <summary> /// True if we should despatch this item to CRM, else false. /// </summary> /// <param name="olItem"></param> /// <returns>true iff settings.SyncCalendar is true, the item is not null, and it is not private (normal sensitivity)</returns> private bool ShouldDespatchToCrm(Outlook.AppointmentItem olItem) { var syncConfigured = SyncDirection.AllowOutbound(Properties.Settings.Default.SyncCalendar); string organiser = olItem.Organizer; var currentUser = Application.Session.CurrentUser; var exchangeUser = currentUser.AddressEntry.GetExchangeUser(); var currentUserName = exchangeUser == null ? Application.Session.CurrentUser.Name: exchangeUser.Name; string crmId = olItem.UserProperties[CrmIdPropertyName]?.Value; return(olItem != null && syncConfigured && olItem.Sensitivity == Outlook.OlSensitivity.olNormal && /* If there is a valid crmId it's arrived via CRM and is therefore safe to save to CRM; * if the current user is the organiser, AND there's no valid CRM id, then it's a new one * that the current user made, and we should save it to CRM. */ (!string.IsNullOrEmpty(crmId) || currentUserName == organiser)); }
/// <summary> /// If I am currently configured to do so, synchronise the items for which I am /// responsible once. /// </summary> internal override void PerformIteration() { if (Globals.ThisAddIn.HasCrmUserSession) { if (SyncDirection.AllowInbound(this.Direction)) { Log.Debug($"{this.GetType().Name} SynchroniseAll starting"); this.SynchroniseAll(); Log.Debug($"{this.GetType().Name} SynchroniseAll completed"); } else { Log.Debug($"{this.GetType().Name}.SynchroniseAll not running because not enabled"); } } else { Log.Debug($"{this.GetType().Name}.SynchroniseAll not running because no session"); } }
/// <summary> /// Does the currently cached value allow access to this module name in this direction? /// </summary> /// <remarks> /// Should never throw a KeyNotFoundException. /// </remarks> /// <param name="moduleKey">The module to which access may be granted.</param> /// <param name="direction">The direction in which access may be granted.</param> /// <returns>True if access is permitted, false if it's denied, null if there's no /// cached value.</returns> private bool?HasCachedAccess(string moduleKey, string direction) { bool?result = null; try { if (CRMPermissionsCache.cache.ContainsKey(moduleKey)) { SyncDirection.Direction cachedValue = CRMPermissionsCache.cache[moduleKey]; result = (direction == ImportPermissionToken && SyncDirection.AllowOutbound(cachedValue)) || (direction == ExportPermissionToken && SyncDirection.AllowInbound(cachedValue)); } } catch (Exception any) { Log.Error("Failed in HasCahedAccess", any); } return(result); }
/// <summary> /// Does the currently cached value allow access to this module name in this direction? /// </summary> /// <remarks> /// Should never throw a KeyNotFoundException. /// </remarks> /// <param name="moduleKey">The module to which access may be granted.</param> /// <param name="direction">The direction in which access may be granted.</param> /// <returns>True if access is permitted, false if it's denied, null if there's no /// cached value.</returns> private bool?HasCachedAccess(string moduleKey, string direction) { bool?result = null; try { if (CRMPermissionsCache.cache.ContainsKey(moduleKey)) { SyncDirection.Direction cachedValue = CRMPermissionsCache.cache[moduleKey]; result = (direction == ImportPermissionToken && SyncDirection.AllowOutbound(cachedValue)) || (direction == ExportPermissionToken && SyncDirection.AllowInbound(cachedValue)); } } catch (Exception any) { ErrorHandler.Handle($"Failed while checking the permissions cache for access to {moduleKey}/{direction}", any); } return(result); }