Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Security;
- using System.Security.Cryptography;
- using System.Text;
- using RG_SRVLib.Interop;
- using Serilog;
- using Serilog.Events;
- using Visma.Core.Security.CryptoServices;
- /*
- * Requires: RG_SRVLib.Interop, Visma.Core.Security.CryptoServices, Serilog
- */
- public class GlobalServerConnection : IDisposable
- {
- private readonly Stack<object> _componentReferences = new Stack<object>();
- private readonly Stopwatch _sw;
- private int _retries;
- private IBisComServer _server;
- public GlobalServerConnection(string clientNumber, string userName, string password, string bapi)
- : this(clientNumber, userName, password.ToSecureString(), bapi)
- {
- }
- public GlobalServerConnection(string clientNumber,
- string userName,
- SecureString password,
- string bapi)
- {
- GlobalClient = clientNumber;
- GlobalUser = userName;
- GlobalPassword = password;
- GlobalBapiKey = bapi;
- if (Log.IsEnabled(LogEventLevel.Debug))
- {
- _sw = Stopwatch.StartNew();
- Log.Debug("GlobalServerConnection({clientNumber}) START", GlobalClient);
- }
- Logon();
- }
- public GlobalServerConnection(IBisCom source)
- {
- _server = source.bcGetServer();
- if (Log.IsEnabled(LogEventLevel.Debug))
- {
- _sw = Stopwatch.StartNew();
- Log.Debug("GlobalServerConnection({clientNumber}) START FROM COMPONENT", GlobalClient);
- }
- }
- public string GlobalClient { get; }
- public string GlobalUser { get; private set; }
- private SecureString GlobalPassword { get; }
- public string GlobalBapiKey { get; }
- public dynamic this[GLOBAL_Components component] => GetComponent((int) component);
- public dynamic this[int component] => GetComponent(component);
- public dynamic this[string component] => GetComponent<IBisCom>(component);
- public void Dispose()
- {
- var count = _componentReferences.Count;
- while (_componentReferences.Any())
- {
- Marshal.ReleaseComObject(_componentReferences.Pop());
- }
- Marshal.ReleaseComObject(_server);
- if (Log.IsEnabled(LogEventLevel.Debug) && _sw != null && _sw.IsRunning)
- {
- _sw.Stop();
- Log.Debug("GlobalServerConnection({clientNumber}) DONE @{elapsed}ms ({componentsUsed} components)",
- GlobalClient, _sw.ElapsedMilliseconds, count);
- }
- GC.SuppressFinalize(this);
- }
- public static List<string> GetAvailableCompanies()
- {
- var compRgSrv = new GlobalServerComponent();
- object arrInputClientId, arrInputDataConnections;
- compRgSrv.bcGetAvailableDataConnections("", "", out arrInputClientId, out arrInputDataConnections);
- var response = ((Array) arrInputDataConnections)?.Cast<string>();
- Marshal.ReleaseComObject(compRgSrv);
- return response?.ToList() ?? new List<string>();
- }
- private void Logon()
- {
- if (_server != null)
- {
- Marshal.ReleaseComObject(_server);
- _server = null;
- }
- _server = new GlobalServerComponent();
- var globalPasswordUnsecure = GlobalPassword.ToUnsecureString();
- string strPassword;
- if (!string.IsNullOrEmpty(GlobalUser) && !string.IsNullOrEmpty(globalPasswordUnsecure))
- {
- var strEncryptKey = _server.bcGetEncryptionKey();
- var strCryptPassword = CredentialEncryption.Encrypt(globalPasswordUnsecure,
- strEncryptKey);
- strPassword = "6C783FE0-B7D2-11DD-8B01-CB9755D89593" + strCryptPassword;
- }
- else
- {
- strPassword = "";
- GlobalUser = "";
- }
- var logon = _server.bcLogon(GlobalClient, GlobalUser, strPassword, GlobalBapiKey);
- if (logon > 0)
- {
- var exception = new GlobalLogonException(logon);
- Log.Fatal(exception, "Logon client {0} failed. Error: {1} ({ret}).", GlobalClient, exception.Message);
- throw exception;
- }
- if (Log.IsEnabled(LogEventLevel.Debug) && _sw != null && _sw.IsRunning)
- {
- Log.Debug("GlobalServerConnection({clientNumber}) LOGON @{elapsed}ms", GlobalClient, _sw.ElapsedMilliseconds);
- }
- }
- private dynamic GetComponent(int component)
- {
- try
- {
- if (_server.bcHaveLicense(component) != 1)
- throw new ComponentLicenseMissingException(
- $"{GlobalClient} does not have license for component {component}");
- if (_server.bcHaveAccess(component) != 1)
- throw new ComponentAccessDeniedException(
- $"{GlobalUser ?? "The current user"} does not have access to component {component}");
- var cmp = _server.bcBusinessComponent[component];
- _retries = 0;
- return cmp;
- }
- catch (COMException e) when (_retries < 3)
- {
- _retries++;
- Log.Error(e, "Connection with Global lost - retrying ({retries}) - {message}", _retries, e.Message);
- Logon();
- return GetComponent(component);
- }
- }
- public T GetComponent<T>(GLOBAL_Components component)
- {
- var comObject = (T) GetComponent((int) component);
- _componentReferences.Push(comObject);
- return comObject;
- }
- public T GetComponent<T>(GLOBAL_Components component, bool establishData) where T : IBisCom
- {
- var comObject = GetComponent<T>(component);
- if (establishData)
- {
- comObject.bcEstablishData();
- comObject.bcBindData();
- }
- return comObject;
- }
- public T GetComponent<T>(string name, bool establishData = false) where T : IBisCom
- {
- object dictionaryObj;
- _server.bcGetSrvDictionary(out dictionaryObj);
- var dictComp = (ISrvDictionary) dictionaryObj;
- var tableId = dictComp.bcGetTableIDFromName(name);
- if (tableId > 0)
- {
- Log.Debug("Found component with name {componentName}. Id is {componentId}", name, tableId);
- var obj = (T) GetComponent(tableId);
- if (establishData)
- {
- obj.bcEstablishData();
- obj.bcBindData();
- }
- return obj;
- }
- return default(T);
- }
- }
- internal class ComponentLicenseMissingException : Exception
- {
- public ComponentLicenseMissingException(string msg) : base(msg)
- {
- }
- }
- internal class ComponentAccessDeniedException : Exception
- {
- public ComponentAccessDeniedException(string msg) : base(msg)
- {
- }
- }
- public class GlobalLogonException : Exception
- {
- private static readonly Dictionary<int, string> Messages = new Dictionary<int, string>
- {
- {11, "Invalid username or password"},
- {12, "Wrong BAPI"},
- {16, "Failed to connect to database"},
- {21, "Too many concurrent users at the moment"},
- {27, "The Visma Global license has expired."},
- {28, "The Visma Global license has expired."}
- };
- public GlobalLogonException(int logon) : base(GetMessage(logon))
- {
- }
- public GlobalLogonException(string msg) : base(msg)
- {
- }
- private static string GetMessage(int errorId)
- {
- string value;
- if (Messages.TryGetValue(errorId, out value))
- return value;
- return $"Generic unknown error ({errorId})";
- }
- }
- public static class IBisComExtentions
- {
- public static Dictionary<string, T> ToDictionary<T>(this IBisComNavigate component, string valueColumn)
- {
- return ToDictionary<T>(component, component.GetObjectIdFromColumnName(valueColumn));
- }
- public static Dictionary<string, TValue> ToDictionary<TValue>(this IBisComNavigate component, int valueColumn)
- {
- var dictionary = new Dictionary<string, TValue>();
- var keyfield = component.bcGetKeyField();
- component.bcFetchFirst(0);
- do
- {
- object value;
- component.bcGetValue(valueColumn, out value);
- dictionary.Add(component.bcGetStr(keyfield), (TValue)value);
- } while (component.bcFetchNext(0) == 0);
- return dictionary;
- }
- public static int GetObjectIdFromColumnName(this IBisCom component, string columnName)
- {
- if (string.IsNullOrEmpty(columnName))
- return 0;
- object varrObjectIds;
- component.bcGetAllObjectIDs(out varrObjectIds, component.bcGetID());
- if (varrObjectIds != null)
- {
- foreach (int objectId in (object[])varrObjectIds)
- {
- if (component.bcGetTableObjectName(objectId).EndsWith($".{columnName}", StringComparison.OrdinalIgnoreCase))
- {
- return objectId;
- }
- }
- }
- Log.Error("Could not find object id for column {name} on component {id}. Available object ids are {@objectids}", columnName, component.bcGetID(), (object[])varrObjectIds);
- return 0;
- }
- public static int Set<T>(this IBisCom component, string columnName, T value, List<int> changedIdList = null)
- {
- var objectId = component.GetObjectIdFromColumnName(columnName);
- if (objectId > 0)
- {
- return Set(component, objectId, value, changedIdList);
- }
- Log.Error("Could not find objectid for {columnName}", columnName);
- return 1;
- }
- public static int Set<T>(this IBisCom component, int objectId, T value, List<int> changedIdList = null)
- {
- var returnValue = SetValueOnComponent(component, objectId, value);
- if (returnValue != 0)
- {
- Log.Error("Could not set value on component. {error}. Component: {component}, ObjectId: {id}, Value: {value}",
- component.bcGetMessageText(returnValue), component.bcGetID(), objectId, value);
- } else {
- changedIdList?.Add(objectId);
- }
- return returnValue;
- }
- private static int SetValueOnComponent<T>(IBisCom component, int objectId, T value)
- {
- if (typeof(T) == typeof(double) || typeof(T) == typeof(decimal))
- return component.bcUpdateDouble(objectId, Convert.ToDouble(value));
- if (typeof(T) == typeof(DateTime))
- return component.bcUpdateDate(objectId, Convert.ToDateTime(value));
- if (typeof(T) == typeof(int) || typeof(T) == typeof(bool))
- return component.bcUpdateInt(objectId, Convert.ToInt32(value));
- return component.bcUpdateStr(objectId, Convert.ToString(value));
- }
- }
- public static class StringExtensions
- {
- public static string Encrypt(this string input)
- {
- if (string.IsNullOrEmpty(input)) return input;
- var bytes = Encoding.UTF8.GetBytes(input);
- var encrypted = ProtectedData.Protect(bytes, null, DataProtectionScope.CurrentUser);
- return Convert.ToBase64String(encrypted);
- }
- public static string Decrypt(this string input)
- {
- if (string.IsNullOrEmpty(input)) return input;
- var bytes = Convert.FromBase64String(input);
- var decrypted = ProtectedData.Unprotect(bytes, null, DataProtectionScope.CurrentUser);
- return Encoding.UTF8.GetString(decrypted);
- }
- public static SecureString DecryptToSecure(this string input)
- {
- if (string.IsNullOrEmpty(input)) return new SecureString();
- var bytes = Convert.FromBase64String(input);
- var decrypted = ProtectedData.Unprotect(bytes, null, DataProtectionScope.CurrentUser);
- var secure = new SecureString();
- foreach (var c in Encoding.UTF8.GetChars(decrypted))
- {
- secure.AppendChar(c);
- }
- secure.MakeReadOnly();
- return secure;
- }
- public static SecureString ToSecureString(this string input)
- {
- var secure = new SecureString();
- if (string.IsNullOrEmpty(input))
- return secure;
- foreach (char c in input)
- {
- secure.AppendChar(c);
- }
- secure.MakeReadOnly();
- return secure;
- }
- public static string ToUnsecureString(this SecureString input)
- {
- if (input == null)
- return "";
- var unmanagedString = IntPtr.Zero;
- try
- {
- unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(input);
- return Marshal.PtrToStringUni(unmanagedString) ?? "";
- }
- finally
- {
- Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement