Пример #1
0
        ///<summary>Turns "pooling" off, then opens the current database connection, adds that connection to the dictionary of MySqlConnections, then returns the unique ServerThread.
        ///The returned ServerThread can then be used later in order to stop the query in the middle of executing.
        ///A non-pooled connection will NOT attempt to re-use connections to the DB that already exist but are idle,
        ///rather it will create a brand new connection that no other connection can use.
        ///This is so that user queries can be safely cancelled if needed.
        ///Required as a first step for user queries (and ONLY user queries).
        ///Not currently Oracle compatible.</summary>
        public static int GetServerThread(bool isReportServer)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetInt(MethodBase.GetCurrentMethod(), isReportServer));
            }
            MySqlConnection con = new MySqlConnection();

            if (isReportServer)
            {
                con = new MySqlConnection(DataConnection.GetReportConnectionString() + ";pooling=false");
            }
            else
            {
                //all connection details are the same, except pooling should be false.
                con = new MySqlConnection(DataConnection.GetCurrentConnectionString() + ";pooling=false");
            }
            con.Open();
            int serverThread = con.ServerThread;

            //If the dictionary already contains the ServerThread key, then something went wrong. Just stop and throw.
            if (_dictCons.ContainsKey(serverThread))
            {
                con.Close();
                throw new ApplicationException("Critical error in GetServerThread: A duplicate connection was found via the server thread ID.");
            }
            lock (_lockObj) {
                _dictCons[serverThread] = con;
            }
            return(serverThread);
        }
Пример #2
0
        ///<summary>NO LONGER USED.
        ///Leaving function here in case we want to reuse the code in future.  We only support connecting to archive DB directly.</summary>
        public static T RunFuncOnArchiveDatabase <T>(Func <T> f)
        {
            //Makes a connection to the archive database, validates that the version of the database is the same as the current database version,
            //executes the func passed in, and then sets the connection back to the original database before returning the results of the func passed in.
            //Optionally pass in connection settings to override the archive preferences.  Throws exceptions.
            if (RemotingClient.RemotingRole.In(RemotingRole.ClientWeb, RemotingRole.ServerWeb))            //May already be behind a remoting role check.
            //This method will eventually invoke SetDB() which is unacceptable for the Middle Tier.
            {
                throw new ApplicationException(Lans.g(nameof(MiscData), "Archive databases are not available when using a Middle Tier connection.") + "\r\n" +
                                               Lans.g(nameof(MiscData), "Archive databases may only be created or accessed on a direct database connection."));
            }
            string         connectionStrOrig = DataConnection.GetCurrentConnectionString();
            DatabaseType   dbTypeOrig        = DataConnection.DBtype;
            DataConnection dcon = new DataConnection();

            try {
                //Keep track of the original connection settings so that we can revert back to them once finished archiving.
                Version versionDbOrig     = new Version(PrefC.GetString(PrefName.DataBaseVersion));
                string  archiveServerName = PrefC.GetString(PrefName.ArchiveServerName);
                string  archiveUserName   = PrefC.GetString(PrefName.ArchiveUserName);
                string  decryptedPass;
                CDT.Class1.Decrypt(PrefC.GetString(PrefName.ArchivePassHash), out decryptedPass);
                //Connect to the archive database.  This can throw many exceptions.
                dcon.SetDb(archiveServerName, MiscData.GetArchiveDatabaseName(), archiveUserName, decryptedPass, "", "", dbTypeOrig);
                #region Validate archive database version
                //At this point there is an active connection to the archive database, validate the DataBaseVersion.
                string version = PrefC.GetStringNoCache(PrefName.DataBaseVersion);
                if (string.IsNullOrEmpty(version))
                {
                    //Preference table does not have version information.  Somehow they have a database with proper structure but no data.
                    //This archive database can't be trusted and we have no idea what version the schema is at.
                    //They need to call support so that we can take a look or they need to delete the invalid archive (or remove it from the data dir)
                    //so that a new archive database can be made from scratch.
                    throw new ApplicationException("Invalid archive database detected.");
                }
                Version versionDbArchive = new Version(version);
                if (versionDbOrig > versionDbArchive)
                {
                    //The archive database needs to be updated before funcs can be invoked against it.
                    throw new ApplicationException("Archive database is at a lower version than the current database."
                                                   + "  Run the Archive tool in order to update the database.");
                }
                else if (versionDbArchive > versionDbOrig)
                {
                    throw new ApplicationException("Archive database version is higher than the current database.  Process cannot continue.");
                }
                #endregion
                //Invoke the func passed in.
                return(f());
            }
            finally {                                          //Always put the connection back to the original no matter what happened above when trying to make an archive.
                dcon.SetDb(connectionStrOrig, "", dbTypeOrig); //It is acceptable to crash the program if this fails.
            }
        }
Пример #3
0
        ///<summary>Used when viewing various audit trails of specific types.  This overload will return security logs for multiple objects (or fKeys).  Typically you will only need a specific type audit log for one type.  However, for things like ortho charts, each row (FK) in the database represents just one part of a larger ortho chart "object".  Thus, to get the full experience of a specific type audit trail window, we need to get security logs for multiple objects (FKs) that comprise the larger object (what the user sees).  Only implemented with ortho chart so far.  FKeys can be null.</summary>
        public static SecurityLog[] Refresh(long patNum, List <Permissions> permTypes, List <long> fKeys, bool includeArchived)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetObject <SecurityLog[]>(MethodBase.GetCurrentMethod(), patNum, permTypes, fKeys, includeArchived));
            }
            string types = "";

            for (int i = 0; i < permTypes.Count; i++)
            {
                if (i > 0)
                {
                    types += " OR";
                }
                types += " PermType=" + POut.Long((int)permTypes[i]);
            }
            string command = "SELECT * FROM securitylog "
                             + "WHERE (" + types + ") ";

            if (fKeys != null && fKeys.Count > 0)
            {
                command += "AND FKey IN (" + String.Join(",", fKeys) + ") ";
            }
            if (patNum != 0)           //appointments
            {
                command += " AND PatNum IN (" + string.Join(",",
                                                            PatientLinks.GetPatNumsLinkedToRecursive(patNum, PatientLinkType.Merge).Select(x => POut.Long(x))) + ")";
            }
            command += "ORDER BY LogDateTime";
            List <SecurityLog> listLogs = Crud.SecurityLogCrud.SelectMany(command);

            if (includeArchived)
            {
                string decryptedPass;
                CDT.Class1.Decrypt(PrefC.GetString(PrefName.ArchivePassHash), out decryptedPass);
                string         connectionStrOrig = DataConnection.GetCurrentConnectionString();
                DatabaseType   dbTypeOrig        = DataConnection.DBtype;
                DataConnection dcon = new DataConnection();
                //Connect to archive database
                dcon.SetDb(PrefC.GetString(PrefName.ArchiveServerName) == ""?PrefC.GetString(PrefName.ArchiveServerURI):PrefC.GetString(PrefName.ArchiveServerName),
                           "opendentalarchive", PrefC.GetString(PrefName.ArchiveUserName), decryptedPass, "", "", dbTypeOrig);
                listLogs.AddRange(Crud.SecurityLogCrud.SelectMany(command)); //Append results
                dcon.SetDb(connectionStrOrig, "", dbTypeOrig);               //Reconnect to initial db
            }
            return(listLogs.OrderBy(x => x.LogDateTime).ToArray());
        }
Пример #4
0
        ///<summary>Turns "pooling" off, then opens the current database connection, adds that connection to the dictionary of MySqlConnections, then returns the unique ServerThread.
        ///The returned ServerThread can then be used later in order to stop the query in the middle of executing.
        ///A non-pooled connection will NOT attempt to re-use connections to the DB that already exist but are idle,
        ///rather it will create a brand new connection that no other connection can use.
        ///This is so that user queries can be safely cancelled if needed.
        ///Required as a first step for user queries (and ONLY user queries).
        ///Not currently Oracle compatible.</summary>
        public static int GetServerThread(bool isReportServer)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetInt(MethodBase.GetCurrentMethod(), isReportServer));
            }
            MySqlConnection con = new MySqlConnection();

            if (isReportServer)
            {
                if (ODBuild.IsWeb() && PrefC.ReportingServer.Server != "" && PrefC.ReportingServer.Database != DataConnection.GetDatabaseName())
                {
                    //Security safeguard to prevent Web users from connecting to another office's database.
                    throw new ODException("Report server database name must match current database.");
                }
                con = new MySqlConnection(
                    DataConnection.GetReportConnectionString(
                        PrefC.ReportingServer.Server
                        , PrefC.ReportingServer.Database
                        , PrefC.ReportingServer.MySqlUser
                        , PrefC.ReportingServer.MySqlPass)
                    + ";pooling=false");
            }
            else
            {
                //Use the database user with lower permissions when in Middle Tier since this method is explicitly designed for the User Query window.
                string connectStr = (RemotingClient.RemotingRole == RemotingRole.ServerWeb ? DataConnection.GetLowConnectionString()
                                        : DataConnection.GetCurrentConnectionString());
                //all connection details are the same, except pooling should be false.
                con = new MySqlConnection(connectStr + ";pooling=false");
            }
            con.Open();
            int serverThread = con.ServerThread;

            //If the dictionary already contains the ServerThread key, then something went wrong. Just stop and throw.
            if (_dictCons.ContainsKey(serverThread))
            {
                con.Close();
                throw new ApplicationException("Critical error in GetServerThread: A duplicate connection was found via the server thread ID.");
            }
            lock (_lockObj) {
                _dictCons[serverThread] = con;
            }
            return(serverThread);
        }
Пример #5
0
        ///<summary>Used when viewing securityLog from the security admin window.  PermTypes can be length 0 to get all types.</summary>
        public static SecurityLog[] Refresh(DateTime dateFrom, DateTime dateTo, Permissions permType, long patNum, long userNum,
                                            DateTime datePreviousFrom, DateTime datePreviousTo, bool includeArchived, int limit = 0)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                return(Meth.GetObject <SecurityLog[]>(MethodBase.GetCurrentMethod(), dateFrom, dateTo, permType, patNum, userNum, datePreviousFrom, datePreviousTo, includeArchived, limit));
            }
            string command = "SELECT securitylog.*,LName,FName,Preferred,MiddleI,LogHash FROM securitylog "
                             + "LEFT JOIN patient ON patient.PatNum=securitylog.PatNum "
                             + "LEFT JOIN securityloghash ON securityloghash.SecurityLogNum=securitylog.SecurityLogNum "
                             + "WHERE LogDateTime >= " + POut.Date(dateFrom) + " "
                             + "AND LogDateTime <= " + POut.Date(dateTo.AddDays(1)) + " "
                             + "AND DateTPrevious >= " + POut.Date(datePreviousFrom) + " "
                             + "AND DateTPrevious <= " + POut.Date(datePreviousTo.AddDays(1));

            if (patNum != 0)
            {
                command += " AND securitylog.PatNum IN (" + string.Join(",",
                                                                        PatientLinks.GetPatNumsLinkedToRecursive(patNum, PatientLinkType.Merge).Select(x => POut.Long(x))) + ")";
            }
            if (permType != Permissions.None)
            {
                command += " AND PermType=" + POut.Long((int)permType);
            }
            if (userNum != 0)
            {
                command += " AND UserNum=" + POut.Long(userNum);
            }
            command += " ORDER BY LogDateTime DESC";          //Using DESC so that the most recent ones appear in the list
            if (limit > 0)
            {
                command = DbHelper.LimitOrderBy(command, limit);
            }
            DataTable          table    = Db.GetTable(command);
            List <SecurityLog> listLogs = Crud.SecurityLogCrud.TableToList(table);

            for (int i = 0; i < listLogs.Count; i++)
            {
                if (table.Rows[i]["PatNum"].ToString() == "0")
                {
                    listLogs[i].PatientName = "";
                }
                else
                {
                    listLogs[i].PatientName = table.Rows[i]["PatNum"].ToString() + "-"
                                              + Patients.GetNameLF(table.Rows[i]["LName"].ToString()
                                                                   , table.Rows[i]["FName"].ToString()
                                                                   , table.Rows[i]["Preferred"].ToString()
                                                                   , table.Rows[i]["MiddleI"].ToString());
                }
                listLogs[i].LogHash = table.Rows[i]["LogHash"].ToString();
            }
            if (includeArchived && dateFrom <= PrefC.GetDate(PrefName.ArchiveDate))           //They are attempting to find security logs that are prior to archived date.
            {
                string decryptedPass;
                CDT.Class1.Decrypt(PrefC.GetString(PrefName.ArchivePassHash), out decryptedPass);
                string         connectionStrOrig = DataConnection.GetCurrentConnectionString();
                DatabaseType   dbTypeOrig        = DataConnection.DBtype;
                DataConnection dcon = new DataConnection();
                //Connect to archive database
                dcon.SetDb(PrefC.GetString(PrefName.ArchiveServerName) == ""?PrefC.GetString(PrefName.ArchiveServerURI):PrefC.GetString(PrefName.ArchiveServerName),
                           "opendentalarchive", PrefC.GetString(PrefName.ArchiveUserName), decryptedPass, "", "", dbTypeOrig);
                DataTable          tableArchive    = Db.GetTable(command);  //Query the archive
                List <SecurityLog> listLogsArchive = Crud.SecurityLogCrud.TableToList(tableArchive);
                dcon.SetDb(connectionStrOrig, "", dbTypeOrig);              //Reconnect to initial db
                Dictionary <long, Patient> dictPats = Patients.GetMultPats(listLogsArchive.Select(x => x.PatNum).Distinct().ToList())
                                                      .ToDictionary(x => x.PatNum);
                for (int i = 0; i < listLogsArchive.Count; i++)
                {
                    Patient pat;
                    if (listLogsArchive[i].PatNum == 0 || !dictPats.TryGetValue(listLogsArchive[i].PatNum, out pat))
                    {
                        listLogsArchive[i].PatientName = "";
                    }
                    else
                    {
                        listLogsArchive[i].PatientName = listLogsArchive[i].PatNum + "-" + pat.GetNameLF();
                    }
                    listLogsArchive[i].LogHash = tableArchive.Rows[i]["LogHash"].ToString();
                }
                listLogs.AddRange(listLogsArchive);                //Add archived entries to returned list.
            }
            return(listLogs.OrderBy(x => x.LogDateTime).ToArray());
        }