/* * dbMango * * Copyright 2025 Deutsche Bank AG * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using Microsoft.Extensions.Options; using MongoDB.Bson; using Rms.Risk.Mango.Interfaces; using Rms.Risk.Mango.Pivot.Core; using Rms.Risk.Mango.Pivot.Core.Models; using Rms.Risk.Mango.Pivot.Core.MongoDb; using Rms.Risk.Mango.Services.Audit; using Rms.Risk.Mango.Services.Context; namespace Rms.Risk.Mango.Services; public class MongoDbServiceFactory : IMongoDbServiceFactory { private const int SessionExpirationMinutes = 30; private const int SessionExpirationCheckMinutes = 5; private record AuditServiceKey(string AuditDatabase, string DatabaseInstance); private record PivotServiceKey(string Database, string DatabaseInstance); private record AdminServiceKey (string Database, string DatabaseInstance, IUserSession Session); private readonly IDatabaseConfigurationService _databases; private readonly IOptions _settings; private IAuditService? _inOracle; private readonly ExpiringConcurrentDictionary _auditServices; private readonly ExpiringConcurrentDictionary _pivotServices; private readonly ExpiringConcurrentDictionary _adminServices; private readonly IDbMangoPlugin? _dbMangoPlugin; public MongoDbServiceFactory(IDatabaseConfigurationService databases, IOptions settings, IDbMangoPlugin? dbMangoPlugin = null) { _databases = databases; _settings = settings; _dbMangoPlugin = dbMangoPlugin; _auditServices = new ( InternalCreateAudit, TimeSpan.FromMinutes(SessionExpirationMinutes), TimeSpan.FromMinutes(SessionExpirationCheckMinutes), false ); _adminServices = new ( InternalCreateAdmin, TimeSpan.FromMinutes(SessionExpirationMinutes), TimeSpan.FromMinutes(SessionExpirationCheckMinutes), false ); _pivotServices = new ( InternalCreatePivot, TimeSpan.FromMinutes(SessionExpirationMinutes), TimeSpan.FromMinutes(SessionExpirationCheckMinutes), false ); } public static MongoDbConfigRecord GetConfig(MongoDbConfigRecord config, string databaseInstance) { if (string.IsNullOrWhiteSpace(config.MongoDbDatabase) && string.IsNullOrWhiteSpace(databaseInstance)) throw new ApplicationException("MongoDB database name is not provided and it's not set in the configuration either."); if (!string.IsNullOrWhiteSpace(databaseInstance)) { var copy = config.Clone(); copy.MongoDbDatabase = databaseInstance; return copy; } return config; } public IPivotTableDataSource CreatePivot(string database, string databaseInstance) => _pivotServices.GetOrAdd(new(database,databaseInstance)); public IMongoDbDatabaseAdminService CreateAdmin(string database, IUserSession session, string databaseInstance) => _adminServices.GetOrAdd(new(database, databaseInstance, session)); public IMongoDbService Create(string database, string collection, string databaseInstance) => new BsonMongoDbService(GetConfig(_databases.Databases[database].Config, databaseInstance), _settings.Value.Settings, collection, databaseInstance); public IMongoDbDatabaseAdminService CreateAdmin(MongoDbConfigRecord config, string auditDatabase, IUserSession session, string databaseInstance) => new AuditedMongoDbDatabaseAdminService( config, _settings.Value.Settings, session, CreateAudit(auditDatabase, string.IsNullOrWhiteSpace(config.MongoDbDatabase) ? databaseInstance : config.MongoDbDatabase), databaseInstance); public IAuditService CreateAudit(string auditDatabase, string databaseInstance) => _auditServices.GetOrAdd(new(auditDatabase,databaseInstance)); #region Internal Methods private IPivotTableDataSource InternalCreatePivot(PivotServiceKey key) => new MongoDbOnlyProxyDataSource(new MongoDbDataSource( GetConfig(_databases.Databases[key.Database].Config, key.DatabaseInstance), _settings.Value.Settings, key.DatabaseInstance )); private IMongoDbDatabaseAdminService InternalCreateAdmin(AdminServiceKey key) => new AuditedMongoDbDatabaseAdminService( GetConfig(_databases.Databases[key.Database].Config, key.DatabaseInstance), _settings.Value.Settings, key.Session, CreateAudit(key.Database, key.DatabaseInstance), key.DatabaseInstance); private IAuditService InternalCreateAudit(AuditServiceKey key) { var inMongo = new AuditService( GetConfig(_databases.Databases[key.AuditDatabase].Config, key.DatabaseInstance), _settings.Value.Settings, _settings.Value.AuditExpireDays ); _inOracle ??= _settings.Value.AuditLogsInOracle && _dbMangoPlugin != null ? _dbMangoPlugin.CreateSecureAuditService(_settings.Value.OracleConnectionSettings) : null; return _inOracle == null ? inMongo : new ChainedAuditService([_inOracle, inMongo]); } #endregion }