/// /// Copyright (c) 2021-2023 Sensus Slovensko a.s. /// using System; using System.Windows.Forms; using NHibernate; using NHibernate.Cfg; using NHibernate.Tool.hbm2ddl; using FluentNHibernate.Cfg; using FluentNHibernate.Cfg.Db; using Common; using Events; using TBF.Resources; using System.Collections.Generic; namespace TBF { public class DB { /// /// Database related: This object reference is set after a successful user login /// public static DatabaseSettings CurrentBench; public static ISessionFactory ConfigDBSessionFactory = null; /// Configuration DB session factory (always != null) public static ISessionFactory SharedDBSessionFactory = null; /// Shared configuration DB session factory or null public static ISessionFactory ResultsDBSessionFactory = null; /// Results DB session factory (always != null) public static ISessionFactory EventsDBSessionFactory = null; /// Events DB session factory or null public static ISessionFactory LocalUsersDBSessionFactory = null; /// Local users DB session factory (always != null) public static ISessionFactory SharedUsersDBSessionFactory = null; /// Shared users DB session factory or null public static ISessionFactory[] UserSessionFactories { get { return (SharedUsersDBSessionFactory != null) ? new ISessionFactory[] { SharedUsersDBSessionFactory, LocalUsersDBSessionFactory } : new ISessionFactory[] { LocalUsersDBSessionFactory }; } } /// /// Create all database session factories /// public static void CreateSessionFactories(DatabaseSettings dbSettings) { /// Configuration database (local, always non-null) if (dbSettings.ProceduresDBSettings != null && dbSettings.ProceduresDBSettings.IsValid) { ConfigDBSessionFactory = CreateSessionFactory(m => m.FluentMappings.AddFromAssemblyOf(), dbSettings.ProceduresDBSettings.DbType, dbSettings.ProceduresDBSettings.ConnectionString); LocalUsersDBSessionFactory = CreateSessionFactory(m => m.FluentMappings.AddFromAssemblyOf(), dbSettings.ProceduresDBSettings.DbType, dbSettings.ProceduresDBSettings.ConnectionString); } /// Shared configuration database (remote) if (dbSettings.UsersDBSettings != null && dbSettings.UsersDBSettings.IsValid) { SharedDBSessionFactory = CreateSessionFactory(m => m.FluentMappings.AddFromAssemblyOf(), dbSettings.UsersDBSettings.DbType, dbSettings.UsersDBSettings.ConnectionString); SharedUsersDBSessionFactory = CreateSessionFactory(m => m.FluentMappings.AddFromAssemblyOf(), dbSettings.UsersDBSettings.DbType, dbSettings.UsersDBSettings.ConnectionString); } /// Results database (local, always non-null) if (dbSettings.WaterMetersDBSettings != null && dbSettings.WaterMetersDBSettings.IsValid) { Results.DB.SessionFactory = ResultsDBSessionFactory = CreateSessionFactory(m => m.FluentMappings.AddFromAssemblyOf(), dbSettings.WaterMetersDBSettings.DbType, dbSettings.WaterMetersDBSettings.ConnectionString); } /// Events database (remote or local) if (dbSettings.EventsDBSettings != null && dbSettings.EventsDBSettings.IsValid) { EventsDBSessionFactory = CreateSessionFactory(m => m.FluentMappings.AddFromAssemblyOf(), dbSettings.EventsDBSettings.DbType, dbSettings.EventsDBSettings.ConnectionString); } } /// /// NHibernate session factory (to create the database session 'SessionFactory') /// /// A database session public static ISessionFactory CreateSessionFactory(Action mappings, DBType dbType, string connectionString, bool createDB = false) { try { var buildSchema = createDB ? (Action)BuildSchemaCreate : (Action)BuildSchema; switch (dbType) { default: case DBType.MySql: return Fluently.Configure() .Database(MySQLConfiguration.Standard.ConnectionString(connectionString)) .Mappings(mappings) .ExposeConfiguration(buildSchema) .BuildConfiguration() .SetProperty("hibernate.connection.connect_timeout", Const.MySqlConnectTimeoutSec) .BuildSessionFactory(); case DBType.SQLite: return Fluently.Configure() .Database(SQLiteConfiguration.Standard.UsingFile(connectionString)) .Mappings(mappings) .ExposeConfiguration(buildSchema) .BuildSessionFactory(); } } catch (Exception exc) { MessageBox.Show(string.Format("{0}: {1}", Strings.Cannot_connect_to_the_database, exc.Message), Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } } static void BuildSchema(Configuration config) { /// This NHibernate tool takes a configuration (with mapping info in) /// and exports a database schema from it new SchemaExport(config).SetOutputFile("db_schema"); } static void BuildSchemaCreate(Configuration config) { /// This NHibernate tool takes a configuration (with mapping info in) /// and exports a database schema from it new SchemaExport(config).Create(true, true); } /// /// Create an empty users database. /// Database contains only the user 'admin' and the control board component 'CB'. /// /// DBType.SQLite or DBType.MySql /// Connection string /// true=success, false=error public static bool CreateEmptyConfigDB(Common.DBType dbType, string connectionString) { ISessionFactory sessionFactory = CreateSessionFactory(m => m.FluentMappings.AddFromAssemblyOf(), dbType, connectionString, true); if (sessionFactory == null) return false; /// Populate the database using (var session = sessionFactory.OpenSession()) { using (var transaction = session.BeginTransaction()) { /// /// Create user 'admin' /// var admin = new Config.Entities.User { UserName = Config.Data.AdminUsername, FullName = Strings.Administrator, LastPwChange = DateTime.Now }; admin.SetPassword(Config.Data.AdminPassword); /// /// Prepare all groups, add some of them to admin /// for (Common.GID gid = 0; gid < Common.GID.NrOfGroups; gid++) { Config.Entities.Group group = new Config.Entities.Group(gid); switch (gid) { case Common.GID.Testers: case Common.GID.TestingSpecialists: case Common.GID.HeadOfLab: case Common.GID.MaintenanceSpecialists: case Common.GID.Metrologists: case Common.GID.CalibrationSpecialists: case Common.GID.Administrators: #if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL case Common.GID.TraceabilityManagement: #elif KEMPNO_50 || KRAKOW_50 || TORUN_50 || WARSAW_50 || WARSAW_END case Common.GID.MetrologicalAuthority: case Common.GID.WaterMeterAuthority: #endif admin.AddGroup(group); session.SaveOrUpdate(group); /// Save this group break; } } session.SaveOrUpdate(admin); /// Save user 'admin' transaction.Commit(); } } return true; } } }