// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Security.Authentication; using System.Threading.Tasks; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; namespace Jupiter.Implementation; public class MongoStore { private readonly string? _overrideDatabaseName; private readonly MongoClient _client; public MongoStore(IOptionsMonitor settings, string? overrideDatabaseName = null) { _overrideDatabaseName = overrideDatabaseName; MongoClientSettings mongoClientSettings = MongoClientSettings.FromUrl( new MongoUrl(settings.CurrentValue.ConnectionString) ); if (settings.CurrentValue.RequireTls12) { mongoClientSettings.SslSettings = new SslSettings { EnabledSslProtocols = SslProtocols.None }; } _client = new MongoClient(mongoClientSettings); } protected async Task CreateCollectionIfNotExistsAsync() { string collectionName = GetCollectionName(); IMongoDatabase database = _client.GetDatabase(GetDatabaseName()); // Try to avoid exceptions breaking in the debugger unnecessarily by checking for the existence of the collection beforehand. FilterDefinition filter = new BsonDocument("name", collectionName); if (await (await database.ListCollectionNamesAsync(new ListCollectionNamesOptions { Filter = filter })).AnyAsync()) { return; } try { await database.CreateCollectionAsync(collectionName); } catch (MongoCommandException e) { if (e.CodeName != "NamespaceExists") { throw; } } } private string GetCollectionName() { object[] attr = typeof(T).GetCustomAttributes(typeof(MongoCollectionNameAttribute), true); foreach (MongoCollectionNameAttribute o in attr) { return o.CollectionName; } throw new ArgumentException($"No MongoCollectionNameAttribute found on type {nameof(T)}"); } protected IMongoIndexManager AddIndexFor() { return GetCollection().Indexes; } protected IMongoCollection GetCollection() { string collectionName = GetCollectionName(); string dbName = GetDatabaseName(); return _client.GetDatabase(dbName).GetCollection(collectionName); } internal string GetDatabaseName() { return _overrideDatabaseName ?? "Jupiter"; } } [AttributeUsage(AttributeTargets.Class)] public sealed class MongoCollectionNameAttribute : Attribute { public string CollectionName { get; } public MongoCollectionNameAttribute(string collectionName) { CollectionName = collectionName; } }