using Microsoft.Extensions.Options; using MongoDB.Driver; using QRBee.Api.Controllers; namespace QRBee.Api.Services.Database { public class Storage: IStorage { private readonly IMongoDatabase _database; private readonly ILogger _logger; public Storage(IMongoClient client, IOptions settings, ILogger logger) { var name = settings.Value.DatabaseName; _database = client.GetDatabase(name); _logger = logger; } public async Task PutUserInfo(UserInfo info) { var collection = _database.GetCollection("Users"); var user = await TryGetUserInfo(info.Email); // Ignore re-register // Potential vulnerability if user registers with other email if (user == null) { await collection.InsertOneAsync(info); _logger.LogInformation($"Inserted new user with Email: {info.Email} and ID: {info.ClientId}"); return info.ClientId ?? throw new ApplicationException($"ClientId is null while adding user {info.Email}"); } // Update command will not be used due to not knowing if the user is legitimate _logger.LogInformation($"Found user with Email: {info.Email} and ID: {info.ClientId}"); return user.ClientId ?? throw new ApplicationException($"ClientId is null while adding user {info.Email}"); } /// /// Check if user already exists in database /// /// Parameter by which to find UserInfo /// null if user doesn't exist or UserInfo internal async Task TryGetUserInfo(string email) { var collection = _database.GetCollection("Users"); using var cursor = await collection.FindAsync($"{{ Email: \"{email}\" }}"); if (!await cursor.MoveNextAsync()) { return null; } return cursor.Current.FirstOrDefault(); } public async Task GetUserInfo(string email) { var user = await TryGetUserInfo(email); return user ?? throw new ApplicationException($"User {email} not found."); } public async Task UpdateUser(UserInfo info) { var collection = _database.GetCollection("Users"); await collection.ReplaceOneAsync($"{{ _id: \"{info.Id}\" }}",info, new ReplaceOptions(){IsUpsert = false}); } } }