using System; using System.Configuration; using System.IO; using System.Linq; using System.ServiceModel; using System.Text.RegularExpressions; using System.Threading; using System.Web.Mvc; using BeWo.Data.Entities; using BeWo.Data.Utils; using BeWo.Service.DCEntityMapper; using BeWo.Service.Security; using BeWoPlanerMobil.Models; using BeWoPlanerMobil.Service; using BeWoPlanerMobil.Util; using BS.Shared; using NHibernate; using NHibernate.Criterion; namespace BeWoPlanerMobil.Controllers { public class ExternalSignatureController : Controller { private static readonly object Lock = string.Empty; protected static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private ExternalSignatureModel _Model; public ExternalSignatureModel Model { get { if (_Model == null) { _Model = new ExternalSignatureModel(); } //if((ExternalSignatureModel) Session["ExternalSignatureModel"] is null) //{ // _Model = new ExternalSignatureModel(); // Session["ExternalSignatureModel"] = _Model; //} //else //{ // _Model = (ExternalSignatureModel) Session["ExternalSignatureModel"]; //} return _Model ?? new ExternalSignatureModel(); } } private bool IsTokenExpired() { if(Model?.Token is null) { return true; } try { var info = SecurityUtils.SliceOneTimeLinkToken(Model.Token); if(info.ContainsKey("expirationDate") && DateTime.TryParse(info["expirationDate"]?.ToString(), out var expirationDate)) { return expirationDate < DateTime.Now; } return true; } catch(Exception exception) { Log.Error(exception.Message, exception); return true; } } private bool CheckCredentials() { if(Model?.Token is null) { return false; } var info = SecurityUtils.SliceOneTimeLinkToken(Model.Token); var username = info["user"].ToString(); var password = info["password"].ToString(); var session = CreateSessionFromTokenInfo(); if(session is null) { return false; } try { var user = session.CreateCriteria() .Add(Restrictions.Eq(nameof(ApplicationUser.LoginName), username)) .Add(Restrictions.Eq(nameof(BeWoEntityBase.IsActive), BS.Shared.ActivationTypeId.Active)) .UniqueResult(); if(!(user is null) && user.CheckRC2Password(password)) { return user.CheckRC2Password(password); } Model.ErrorMessage = "Es ist ein Fehler aufgetreten.
Bitte wenden Sie sich an Ihren Administrator"; #if DEBUG //Model.ErrorMessage = $"Es wurde kein Benutzer mit dem Loginnamen {username} gefunden oder das Passwort stimmt nicht überein!"; #endif return false; } catch(Exception exception) { throw exception; } finally { session.Close(); } } private ISession CreateSessionFromTokenInfo() { try { Monitor.Enter(Lock); var test = System.Web.HttpContext.Current.Server.MapPath(""); var dotDotCount = Regex.Matches(test, "ExternalSignature").Count; var mapPathParameter = ""; for(var i = 0; i < dotDotCount; i++) { mapPathParameter += "..\\"; } var serverPath = System.Web.HttpContext.Current.Server.MapPath(mapPathParameter); serverPath = Path.Combine(serverPath, ConfigurationManager.AppSettings.Get("MultitenancyPath")); serverPath = Path.Combine(serverPath, $"{Model.Tenant}.config"); if(!System.IO.File.Exists(serverPath)) { Model.ErrorMessage = "Es ist ein Fehler aufgetreten.
Bitte wenden Sie sich an Ihren Administrator"; #if DEBUG //Model.ErrorMessage = "Die .config-Datei wurde nicht gefunden!"; #endif return null; } var config = new NHibernate.Cfg.Configuration().Configure(serverPath).SetInterceptor(new MobileUpdInsInterceptor()).BuildSessionFactory(); return config.OpenSession(); } catch(Exception exception) { throw new FaultException(exception.StackTrace + (exception.InnerException?.Message ?? string.Empty)); } finally { Monitor.Exit(Lock); } } private ServiceRecord LoadServiceRecord() { try { if(false == CheckCredentials() || IsTokenExpired()) { return null; } var session = CreateSessionFromTokenInfo(); try { if(Model.ServiceRecordOid is null) { return null; } return session.CreateCriteria() .Add(Restrictions.Eq(nameof(BeWoEntityBase.Oid), Model.ServiceRecordOid)) .Add(Restrictions.Eq(nameof(BeWoEntityBase.IsActive), ActivationTypeId.Active)) .UniqueResult(); } catch(Exception exception) { throw exception; } finally { session.Close(); } } catch(Exception exception) { Log.Error(exception.Message, exception); return null; } } public ActionResult ExternalSignature(string token) { if(token is null) { Model.ErrorMessage = "Es ist ein Fehler aufgetreten.
Bitte wenden Sie sich an Ihren Administrator"; #if DEBUG Model.ErrorMessage = "Token ist null!"; #endif return View(Model); } try { Model.Token = token; var info = SecurityUtils.SliceOneTimeLinkToken(token); if(IsTokenExpired()) { Model.ErrorMessage = "Der Link ist abgelaufen!"; return View(Model); } Model.Tenant = info["tenant"].ToString(); var username = info["user"].ToString(); var serviceRecordOid = long.Parse(info["serviceRecordOid"].ToString()); var session = CreateSessionFromTokenInfo(); if(session is null) { return View(Model); } if(false == CheckCredentials()) { Model.ErrorMessage = "Es ist ein Fehler aufgetreten.
Bitte wenden Sie sich an Ihren Administrator."; #if DEBUG //Model.ErrorMessage = $"Es wurde kein Benutzer mit dem Loginnamen {username} gefunden oder das Passwort stimmt nicht überein!"; #endif return View(Model); } try { var serviceRecord = session.CreateCriteria() .Add(Restrictions.Eq(nameof(BeWoEntityBase.Oid), serviceRecordOid)) .Add(Restrictions.Eq(nameof(BeWoEntityBase.IsActive), BS.Shared.ActivationTypeId.Active)) .UniqueResult(); if(serviceRecord is null) { Model.ErrorMessage = "Es ist ein Fehler aufgetreten.
Bitte wenden Sie sich an Ihren Administrator."; #if DEBUG //Model.TestInfo = $"Es wurde kein ServiceRecord mit der Oid {serviceRecordOid} gefunden!"; #endif return View(Model); } if(serviceRecord.SignatureOid.HasValue) { Model.HasSignatureAlready = true; return View(Model); } var auswahlBezeichnung = serviceRecord.CostBearer2SupportConcept.AuswahlBezeichnung; var cb2ScStart = serviceRecord.CostBearer2SupportConcept.StartDate?.ToShortDateString().Remove(6, 2) ?? string.Empty; var cb2ScEnd = serviceRecord.CostBearer2SupportConcept.EndDate?.ToShortDateString().Remove(6, 2) ?? string.Empty; var costBearerName = serviceRecord.CostBearer2SupportConcept.CostBearer.Organisation.Name; var approvalInfo = GetIsNotApproved(serviceRecord.CostBearer2SupportConcept); var customerDC = MapperFactory.CompactCustomerDC_Customer.MapToNewDC(serviceRecord.Customer); Model.SupportConceptInfo = $"{customerDC.SimpleDescription} {customerDC.DateOfBirthString ?? string.Empty} | {auswahlBezeichnung} {cb2ScStart}-{cb2ScEnd} {costBearerName}{approvalInfo}"; Model.ServiceDescriptionInfo = serviceRecord.ServiceDescription.Name; Model.CategoryInfo = serviceRecord.ServiceDescription.ServiceCategory.Name; Model.EmployeeInfo = serviceRecord.Employee.Person.LastNameFirstName; Model.ServiceRecordDateTime = MainModel.GetServiceRecordTimeString(MapperFactory.ServiceRecordDC_ServiceRecord.MapToNewDC(serviceRecord)); Model.ServiceRecordOid = serviceRecord.Oid; Model.CustomerName = customerDC.Name; } catch(Exception exception) { throw exception; } finally { session.Close(); } } catch(Exception exception) { Log.Error(exception.Message, exception); Model.ErrorMessage = exception.Message + "

" + exception.StackTrace; } return View(Model); } public string SaveSignature(string base64Image, DateTime creationDate) { try { long? oid; using(var signatureBitmap = SignatureUtils.Base64StringToBitmap(base64Image.Split(',')[1])) { var isValid = SignatureUtils.ValidateSignature(signatureBitmap); if(!isValid) { return "Das Unterschriftenfeld darf nicht leer sein."; } var signature = new Signature { DataBild = base64Image, IsActive = ActivationTypeId.Active, ServiceRecordOid = Model.ServiceRecordOid, Zeitstempel = creationDate }; Insert(signature); oid = signature.Oid; var serviceRecord = LoadServiceRecord(); serviceRecord.SignatureOid = signature.Oid; var session = CreateSessionFromTokenInfo(); if(session is null) { throw new InvalidOperationException("Database session is null!"); } var transaction = session.BeginTransaction(); try { BeWo.Service.Core.ServiceLogic.ConcurrencyCheck(serviceRecord.Version, LoadServiceRecord()); session.Update(serviceRecord); transaction.Commit(); transaction = session.BeginTransaction(); var previousRecordHistorySignatureInfo = FindMostRecentSignatureStatusInfo(); var seviceRecordHistoryEntry = new ServiceRecordHistory { TimeStamp = DateTime.Now, ChangeType = StatementType.Signature, CostBearer2SupportConcept = serviceRecord.CostBearer2SupportConcept, CostBearer2SupportConceptOid = serviceRecord.CostBearer2SupportConceptOid, Customer = serviceRecord.Customer, CustomerOid = serviceRecord.CustomerOid, Employee = serviceRecord.Employee, EmployeeOid = serviceRecord.EmployeeOid, End = serviceRecord.End, Group = serviceRecord.Group, GroupEmployeeCount = serviceRecord.GroupEmployeeCount, GroupOid = serviceRecord.GroupOid, GroupPersonCount = serviceRecord.GroupPersonCount, GroupRoundedDuration = serviceRecord.GroupRoundedDuration, IP = serviceRecord.IP, IsActive = serviceRecord.IsActive, Notice = serviceRecord.Notice, ServiceRecordOid = serviceRecord.Oid, RoundedDuration = serviceRecord.RoundedDuration, ServiceDescription = serviceRecord.ServiceDescription, ServiceRecordType = serviceRecord.ServiceRecordType, ServiceRecordInsTs = serviceRecord.InsTs, ServiceRecordVersion = serviceRecord.Version.Value, ServiceRecordInsUser = serviceRecord.InsUser, ServiceRecordUdpUser = serviceRecord.UdpUser, Start = serviceRecord.Start, SupportConcept = serviceRecord.SupportConcept, SystemEntryID = serviceRecord.SystemEntryID, DistanceInMeter = serviceRecord.DistanceInMeter, IsCreatedInMobileClient = serviceRecord.IsCreatedInMobileClient, CustomerConfirmationReceiptSignatureStateType = SignatureStateType.Valid, EmployeeConfirmationReceiptSignatureStateType = previousRecordHistorySignatureInfo?.EmployeeConfirmationReceiptSignatureStateType ?? SignatureStateType.None, ServiceRecordSignatureStateType = previousRecordHistorySignatureInfo?.ServiceRecordSignatureStateType ?? SignatureStateType.None, CustomerConfirmationReceiptSignatureOid = previousRecordHistorySignatureInfo?.CustomerConfirmationReceiptSignatureOid, EmployeeConfirmationReceiptSignatureOid = previousRecordHistorySignatureInfo?.EmployeeConfirmationReceiptSignatureOid }; session.Save(seviceRecordHistoryEntry); transaction.Commit(); } catch(Exception exception) { transaction.Rollback(); throw exception; } finally { session.Close(); } } return oid.HasValue ? "1" : "0"; } catch(Exception outerException) { Log.Error(outerException.Message, outerException); return "0"; } } private void Insert(BeWoEntityBase entity) { try { var session = CreateSessionFromTokenInfo(); if(session is null || false == CheckCredentials()) { throw new InvalidOperationException("Database session is null!"); } var transaction = session.BeginTransaction(); try { session.Save(entity); transaction.Commit(); } catch(Exception exception) { transaction.Rollback(); throw exception; } finally { session.Close(); } } catch(Exception exception) { Log.Error(exception.Message, exception); } } private SignatureStateInfoFromServiceRecordHistoryEntry FindMostRecentSignatureStatusInfo() { var session = CreateSessionFromTokenInfo(); var sqlQuery = session.CreateSQLQuery($"SELECT * FROM ServiceRecordHistory WHERE ServiceRecordOid = {Model.ServiceRecordOid} ORDER BY InsTs DESC LIMIT 1") .AddScalar("CustomerConfirmationReceiptSignatureStateType", NHibernateUtil.Int32) .AddScalar("EmployeeConfirmationReceiptSignatureStateType", NHibernateUtil.Int32) .AddScalar("ServiceRecordSignatureStateType", NHibernateUtil.Int32) .AddScalar("CustomerConfirmationReceiptSignatureOid", NHibernateUtil.Int64) .AddScalar("EmployeeConfirmationReceiptSignatureOid", NHibernateUtil.Int64); var objectsList = sqlQuery.List().ToList(); var row = objectsList.FirstOrDefault(); if(row is null || row.Length != 5) { return null; } var customerConfirmationReceiptSignatureState = (SignatureStateType) row[0]; var employeeConfirmationReceiptSignatureState = (SignatureStateType) row[1]; var serviceRecordSignatureStateType = (SignatureStateType) row[2]; var customerConfirmationReceiptSignatureOid = (long?) row[3]; var employeeConfirmationReceiptSignatureOid = (long?) row[4]; return new SignatureStateInfoFromServiceRecordHistoryEntry(customerConfirmationReceiptSignatureState, employeeConfirmationReceiptSignatureState, serviceRecordSignatureStateType, customerConfirmationReceiptSignatureOid, employeeConfirmationReceiptSignatureOid); } private static string GetIsNotApproved(CostBearer2SupportConcept costBearer2SupportConcept) { var result = string.Empty; var customer = costBearer2SupportConcept?.SupportConcept?.Customer; if(customer?.TerminationDate.HasValue ?? false) { var terminationReason = string.Empty; if(!string.IsNullOrEmpty(customer.TerminationReason.Value)) { terminationReason += $", Begründung: {customer.TerminationReason}"; } result += $" (Betreuung beendet am: {customer.TerminationDate:dd.MM.yyyy}{terminationReason})"; } if(costBearer2SupportConcept?.ApprovedStartDate is null || costBearer2SupportConcept.ApprovedEndDate is null) { result += " nicht bewilligt!"; } return result; } } }