From be432dfd24561792a54381708881267684a24e09 Mon Sep 17 00:00:00 2001 From: Abdullah Atta Date: Tue, 14 Oct 2025 09:28:41 +0500 Subject: [PATCH] global: migrate to using ILogger --- .../Accessors/SyncItemsRepositoryAccessor.cs | 27 +++++----- Notesnook.API/Controllers/InboxController.cs | 40 ++++++-------- .../Controllers/MonographsController.cs | 11 ++-- .../Controllers/SyncDeviceController.cs | 11 ++-- Notesnook.API/Controllers/UsersController.cs | 11 ++-- .../Repositories/SyncItemsRepository.cs | 11 ++-- Notesnook.API/Services/UserService.cs | 35 +++++-------- Streetwriters.Common/Logger.cs | 52 ------------------- Streetwriters.Common/Services/EmailSender.cs | 11 +++- Streetwriters.Common/WampServers.cs | 24 ++------- .../Controllers/AccountController.cs | 7 ++- .../Controllers/SignupController.cs | 16 ++++-- .../Services/EmailAddressValidator.cs | 11 +++- Streetwriters.Identity/Services/MFAService.cs | 7 ++- 14 files changed, 113 insertions(+), 161 deletions(-) delete mode 100644 Streetwriters.Common/Logger.cs diff --git a/Notesnook.API/Accessors/SyncItemsRepositoryAccessor.cs b/Notesnook.API/Accessors/SyncItemsRepositoryAccessor.cs index fbc264d..cdfb34a 100644 --- a/Notesnook.API/Accessors/SyncItemsRepositoryAccessor.cs +++ b/Notesnook.API/Accessors/SyncItemsRepositoryAccessor.cs @@ -18,6 +18,7 @@ along with this program. If not, see . */ using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using MongoDB.Driver; using Notesnook.API.Interfaces; using Notesnook.API.Models; @@ -74,24 +75,24 @@ namespace Notesnook.API.Accessors IMongoCollection tags, Repository usersSettings, Repository monographs, - Repository inboxApiKey, Repository inboxItems) + Repository inboxApiKey, Repository inboxItems, ILogger logger) { UsersSettings = usersSettings; Monographs = monographs; InboxApiKey = inboxApiKey; InboxItems = inboxItems; - Notebooks = new SyncItemsRepository(dbContext, notebooks); - Notes = new SyncItemsRepository(dbContext, notes); - Contents = new SyncItemsRepository(dbContext, content); - Settings = new SyncItemsRepository(dbContext, settings); - LegacySettings = new SyncItemsRepository(dbContext, legacySettings); - Attachments = new SyncItemsRepository(dbContext, attachments); - Shortcuts = new SyncItemsRepository(dbContext, shortcuts); - Reminders = new SyncItemsRepository(dbContext, reminders); - Relations = new SyncItemsRepository(dbContext, relations); - Colors = new SyncItemsRepository(dbContext, colors); - Vaults = new SyncItemsRepository(dbContext, vaults); - Tags = new SyncItemsRepository(dbContext, tags); + Notebooks = new SyncItemsRepository(dbContext, notebooks, logger); + Notes = new SyncItemsRepository(dbContext, notes, logger); + Contents = new SyncItemsRepository(dbContext, content, logger); + Settings = new SyncItemsRepository(dbContext, settings, logger); + LegacySettings = new SyncItemsRepository(dbContext, legacySettings, logger); + Attachments = new SyncItemsRepository(dbContext, attachments, logger); + Shortcuts = new SyncItemsRepository(dbContext, shortcuts, logger); + Reminders = new SyncItemsRepository(dbContext, reminders, logger); + Relations = new SyncItemsRepository(dbContext, relations, logger); + Colors = new SyncItemsRepository(dbContext, colors, logger); + Vaults = new SyncItemsRepository(dbContext, vaults, logger); + Tags = new SyncItemsRepository(dbContext, tags, logger); } } } \ No newline at end of file diff --git a/Notesnook.API/Controllers/InboxController.cs b/Notesnook.API/Controllers/InboxController.cs index cdb277e..d57b003 100644 --- a/Notesnook.API/Controllers/InboxController.cs +++ b/Notesnook.API/Controllers/InboxController.cs @@ -23,6 +23,7 @@ using System.Text.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; using MongoDB.Bson; using Notesnook.API.Authorization; using Notesnook.API.Models; @@ -35,21 +36,12 @@ namespace Notesnook.API.Controllers { [ApiController] [Route("inbox")] - public class InboxController : ControllerBase - { - private readonly Repository InboxApiKey; - private readonly Repository UserSetting; - private Repository InboxItems; - - public InboxController( + public class InboxController( Repository inboxApiKeysRepository, Repository userSettingsRepository, - Repository inboxItemsRepository) - { - InboxApiKey = inboxApiKeysRepository; - UserSetting = userSettingsRepository; - InboxItems = inboxItemsRepository; - } + Repository inboxItemsRepository, + ILogger logger) : ControllerBase + { [HttpGet("api-keys")] [Authorize(Policy = "Notesnook")] @@ -58,12 +50,12 @@ namespace Notesnook.API.Controllers var userId = User.FindFirstValue("sub"); try { - var apiKeys = await InboxApiKey.FindAsync(t => t.UserId == userId); + var apiKeys = await inboxApiKeysRepository.FindAsync(t => t.UserId == userId); return Ok(apiKeys); } catch (Exception ex) { - await Slogger.Error(nameof(GetApiKeysAsync), "Couldn't get inbox api keys.", userId, ex.ToString()); + logger.LogError(ex, "Couldn't get inbox api keys for user {UserId}", userId); return BadRequest(new { error = ex.Message }); } } @@ -84,7 +76,7 @@ namespace Notesnook.API.Controllers return BadRequest(new { error = "Valid expiry date is required." }); } - var count = await InboxApiKey.CountAsync(t => t.UserId == userId); + var count = await inboxApiKeysRepository.CountAsync(t => t.UserId == userId); if (count >= 10) { return BadRequest(new { error = "Maximum of 10 inbox api keys allowed." }); @@ -98,12 +90,12 @@ namespace Notesnook.API.Controllers ExpiryDate = request.ExpiryDate, LastUsedAt = 0 }; - await InboxApiKey.InsertAsync(inboxApiKey); + await inboxApiKeysRepository.InsertAsync(inboxApiKey); return Ok(inboxApiKey); } catch (Exception ex) { - await Slogger.Error(nameof(CreateApiKeyAsync), "Couldn't create inbox api key.", userId, ex.ToString()); + logger.LogError(ex, "Couldn't create inbox api key for {UserId}.", userId); return BadRequest(new { error = ex.Message }); } } @@ -120,12 +112,12 @@ namespace Notesnook.API.Controllers return BadRequest(new { error = "Api key is required." }); } - await InboxApiKey.DeleteAsync(t => t.UserId == userId && t.Key == apiKey); + await inboxApiKeysRepository.DeleteAsync(t => t.UserId == userId && t.Key == apiKey); return Ok(new { message = "Api key deleted successfully." }); } catch (Exception ex) { - await Slogger.Error(nameof(DeleteApiKeyAsync), "Couldn't delete inbox api key.", userId, ex.ToString()); + logger.LogError(ex, "Couldn't delete inbox api key for user {UserId}", userId); return BadRequest(new { error = ex.Message }); } } @@ -137,7 +129,7 @@ namespace Notesnook.API.Controllers var userId = User.FindFirstValue("sub"); try { - var userSetting = await UserSetting.FindOneAsync(u => u.UserId == userId); + var userSetting = await userSettingsRepository.FindOneAsync(u => u.UserId == userId); if (string.IsNullOrWhiteSpace(userSetting?.InboxKeys?.Public)) { return BadRequest(new { error = "Inbox public key is not configured." }); @@ -146,7 +138,7 @@ namespace Notesnook.API.Controllers } catch (Exception ex) { - await Slogger.Error(nameof(GetPublicKeyAsync), "Couldn't get user's inbox's public key.", userId, ex.ToString()); + logger.LogError(ex, "Couldn't get user's inbox's public key for user {UserId}", userId); return BadRequest(new { error = ex.Message }); } } @@ -189,7 +181,7 @@ namespace Notesnook.API.Controllers request.UserId = userId; request.ItemId = ObjectId.GenerateNewId().ToString(); - await InboxItems.InsertAsync(request); + await inboxItemsRepository.InsertAsync(request); new SyncDeviceService(new SyncDevice(userId, string.Empty)) .AddIdsToAllDevices([$"{request.ItemId}:inboxItems"]); await WampServers.MessengerServer.PublishMessageAsync(MessengerServerTopics.SendSSETopic, new SendSSEMessage @@ -206,7 +198,7 @@ namespace Notesnook.API.Controllers } catch (Exception ex) { - await Slogger.Error(nameof(CreateInboxItemAsync), "Couldn't create inbox item.", userId, ex.ToString()); + logger.LogError(ex, "Couldn't create inbox item for user {UserId}", userId); return BadRequest(new { error = ex.Message }); } } diff --git a/Notesnook.API/Controllers/MonographsController.cs b/Notesnook.API/Controllers/MonographsController.cs index 7a0e38d..c0f2d85 100644 --- a/Notesnook.API/Controllers/MonographsController.cs +++ b/Notesnook.API/Controllers/MonographsController.cs @@ -27,6 +27,7 @@ using AngleSharp; using AngleSharp.Dom; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; using MongoDB.Bson; using MongoDB.Driver; using Notesnook.API.Authorization; @@ -43,7 +44,7 @@ namespace Notesnook.API.Controllers [ApiController] [Route("monographs")] [Authorize("Sync")] - public class MonographsController(Repository monographs, IURLAnalyzer analyzer) : ControllerBase + public class MonographsController(Repository monographs, IURLAnalyzer analyzer, ILogger logger) : ControllerBase { const string SVG_PIXEL = ""; private const int MAX_DOC_SIZE = 15 * 1024 * 1024; @@ -133,7 +134,7 @@ namespace Notesnook.API.Controllers } catch (Exception e) { - await Slogger.Error(nameof(PublishAsync), e.ToString()); + logger.LogError(e, "Failed to publish monograph"); return BadRequest(); } } @@ -184,7 +185,7 @@ namespace Notesnook.API.Controllers } catch (Exception e) { - await Slogger.Error(nameof(UpdateAsync), e.ToString()); + logger.LogError(e, "Failed to update monograph"); return BadRequest(); } } @@ -328,7 +329,7 @@ namespace Notesnook.API.Controllers if (string.IsNullOrEmpty(href)) continue; if (!await analyzer.IsURLSafeAsync(href)) { - await Slogger.Info("CleanupContentAsync", "Malicious URL detected: " + href); + logger.LogInformation("Malicious URL detected: {Url}", href); element.RemoveAttribute("href"); } } @@ -355,7 +356,7 @@ namespace Notesnook.API.Controllers } catch (Exception ex) { - await Slogger.Error("CleanupContentAsync", ex.ToString()); + logger.LogError(ex, "Failed to cleanup monograph content"); return content; } } diff --git a/Notesnook.API/Controllers/SyncDeviceController.cs b/Notesnook.API/Controllers/SyncDeviceController.cs index 7b2aeca..8cf964c 100644 --- a/Notesnook.API/Controllers/SyncDeviceController.cs +++ b/Notesnook.API/Controllers/SyncDeviceController.cs @@ -24,6 +24,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; using Notesnook.API.Interfaces; using Notesnook.API.Models.Responses; using Notesnook.API.Services; @@ -36,10 +37,10 @@ namespace Notesnook.API.Controllers [ApiController] [Authorize] [Route("devices")] - public class SyncDeviceController : ControllerBase + public class SyncDeviceController(ILogger logger) : ControllerBase { [HttpPost] - public async Task RegisterDevice([FromQuery] string deviceId) + public IActionResult RegisterDevice([FromQuery] string deviceId) { try { @@ -49,14 +50,14 @@ namespace Notesnook.API.Controllers } catch (Exception ex) { - await Slogger.Error(nameof(UnregisterDevice), "Couldn't register device.", ex.ToString()); + logger.LogError(ex, "Failed to register device: {DeviceId}", deviceId); return BadRequest(new { error = ex.Message }); } } [HttpDelete] - public async Task UnregisterDevice([FromQuery] string deviceId) + public IActionResult UnregisterDevice([FromQuery] string deviceId) { try { @@ -66,7 +67,7 @@ namespace Notesnook.API.Controllers } catch (Exception ex) { - await Slogger.Error(nameof(UnregisterDevice), "Couldn't unregister device.", ex.ToString()); + logger.LogError(ex, "Failed to unregister device: {DeviceId}", deviceId); return BadRequest(new { error = ex.Message }); } } diff --git a/Notesnook.API/Controllers/UsersController.cs b/Notesnook.API/Controllers/UsersController.cs index eee1418..ede4fa4 100644 --- a/Notesnook.API/Controllers/UsersController.cs +++ b/Notesnook.API/Controllers/UsersController.cs @@ -23,6 +23,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http.Timeouts; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; using Notesnook.API.Interfaces; using Notesnook.API.Models; using Notesnook.API.Models.Responses; @@ -33,7 +34,7 @@ namespace Notesnook.API.Controllers [ApiController] [Authorize] [Route("users")] - public class UsersController(IUserService UserService) : ControllerBase + public class UsersController(IUserService UserService, ILogger logger) : ControllerBase { [HttpPost] [AllowAnonymous] @@ -46,7 +47,7 @@ namespace Notesnook.API.Controllers } catch (Exception ex) { - await Slogger.Error(nameof(Signup), "Couldn't sign up.", ex.ToString()); + logger.LogError(ex, "Failed to sign up user"); return BadRequest(new { error = ex.Message }); } } @@ -63,7 +64,7 @@ namespace Notesnook.API.Controllers } catch (Exception ex) { - await Slogger.Error(nameof(GetUser), "Couldn't get user for id.", userId, ex.ToString()); + logger.LogError(ex, "Failed to get user with id: {UserId}", userId); return BadRequest(new { error = ex.Message }); } } @@ -79,7 +80,7 @@ namespace Notesnook.API.Controllers } catch (Exception ex) { - await Slogger.Error(nameof(GetUser), "Couldn't update user with id.", userId, ex.ToString()); + logger.LogError(ex, "Failed to update user with id: {UserId}", userId); return BadRequest(new { error = ex.Message }); } } @@ -107,7 +108,7 @@ namespace Notesnook.API.Controllers } catch (Exception ex) { - await Slogger.Error(nameof(GetUser), "Couldn't delete user with id.", userId, ex.ToString()); + logger.LogError(ex, "Failed to delete user with id: {UserId}", userId); return BadRequest(new { error = ex.Message }); } } diff --git a/Notesnook.API/Repositories/SyncItemsRepository.cs b/Notesnook.API/Repositories/SyncItemsRepository.cs index a22b0fd..e0f0925 100644 --- a/Notesnook.API/Repositories/SyncItemsRepository.cs +++ b/Notesnook.API/Repositories/SyncItemsRepository.cs @@ -26,6 +26,7 @@ using System.Threading; using System.Threading.Tasks; using IdentityModel; using Microsoft.VisualBasic; +using Microsoft.Extensions.Logging; using MongoDB.Bson; using MongoDB.Driver; using Notesnook.API.Hubs; @@ -41,9 +42,11 @@ namespace Notesnook.API.Repositories public class SyncItemsRepository : Repository { private readonly string collectionName; - public SyncItemsRepository(IDbContext dbContext, IMongoCollection collection) : base(dbContext, collection) + private readonly ILogger logger; + public SyncItemsRepository(IDbContext dbContext, IMongoCollection collection, ILogger logger) : base(dbContext, collection) { this.collectionName = collection.CollectionNamespace.CollectionName; + this.logger = logger; } private readonly List ALGORITHMS = [Algorithms.Default, Algorithms.XSAL_X25519_7]; @@ -110,7 +113,8 @@ namespace Notesnook.API.Repositories // Handle case where the cipher is corrupted. if (!IsBase64String(item.Cipher)) { - Slogger.Error("Upsert", "Corrupted", item.ItemId, item.Length.ToString(), item.Cipher); + logger.LogError("Corrupted item {ItemId} in collection {CollectionName}. Length: {Length}, Cipher: {Cipher}", + item.ItemId, this.collectionName, item.Length, item.Cipher); throw new Exception($"Corrupted item \"{item.ItemId}\" in collection \"{this.collectionName}\". Please report this error to support@streetwriters.co."); } @@ -147,7 +151,8 @@ namespace Notesnook.API.Repositories // Handle case where the cipher is corrupted. if (!IsBase64String(item.Cipher)) { - Slogger.Error("Upsert", "Corrupted", item.ItemId, item.Length.ToString(), item.Cipher); + logger.LogError("Corrupted item {ItemId} in collection {CollectionName}. Length: {Length}, Cipher: {Cipher}", + item.ItemId, this.collectionName, item.Length, item.Cipher); throw new Exception($"Corrupted item \"{item.ItemId}\" in collection \"{this.collectionName}\". Please report this error to support@streetwriters.co."); } diff --git a/Notesnook.API/Services/UserService.cs b/Notesnook.API/Services/UserService.cs index 54f311b..b587868 100644 --- a/Notesnook.API/Services/UserService.cs +++ b/Notesnook.API/Services/UserService.cs @@ -23,6 +23,7 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Notesnook.API.Helpers; using Notesnook.API.Interfaces; using Notesnook.API.Models; @@ -37,33 +38,23 @@ using Streetwriters.Data.Interfaces; namespace Notesnook.API.Services { - public class UserService : IUserService + public class UserService(IHttpContextAccessor accessor, + ISyncItemsRepositoryAccessor syncItemsRepositoryAccessor, + IUnitOfWork unitOfWork, IS3Service s3Service, ILogger logger) : IUserService { private static readonly System.Security.Cryptography.RandomNumberGenerator Rng = System.Security.Cryptography.RandomNumberGenerator.Create(); - private readonly HttpClient httpClient; - private IHttpContextAccessor HttpContextAccessor { get; } - private ISyncItemsRepositoryAccessor Repositories { get; } - private IS3Service S3Service { get; set; } - private readonly IUnitOfWork unit; - - public UserService(IHttpContextAccessor accessor, - ISyncItemsRepositoryAccessor syncItemsRepositoryAccessor, - IUnitOfWork unitOfWork, IS3Service s3Service) - { - httpClient = new HttpClient(); - - Repositories = syncItemsRepositoryAccessor; - HttpContextAccessor = accessor; - unit = unitOfWork; - S3Service = s3Service; - } + private readonly HttpClient httpClient = new(); + private IHttpContextAccessor HttpContextAccessor { get; } = accessor; + private ISyncItemsRepositoryAccessor Repositories { get; } = syncItemsRepositoryAccessor; + private IS3Service S3Service { get; set; } = s3Service; + private readonly IUnitOfWork unit = unitOfWork; public async Task CreateUserAsync() { SignupResponse response = await httpClient.ForwardAsync(this.HttpContextAccessor, $"{Servers.IdentityServer}/signup", HttpMethod.Post); if (!response.Success || (response.Errors != null && response.Errors.Length > 0)) { - await Slogger.Error(nameof(CreateUserAsync), "Couldn't sign up.", JsonSerializer.Serialize(response)); + logger.LogError("Failed to sign up user: {Response}", JsonSerializer.Serialize(response)); if (response.Errors != null && response.Errors.Length > 0) throw new Exception(string.Join(" ", response.Errors)); else throw new Exception("Could not create a new account. Error code: " + response.StatusCode); @@ -91,7 +82,7 @@ namespace Notesnook.API.Services }); } - await Slogger.Info(nameof(CreateUserAsync), "New user created.", JsonSerializer.Serialize(response)); + logger.LogInformation("New user created: {Response}", JsonSerializer.Serialize(response)); } public async Task GetUserAsync(string userId) @@ -210,7 +201,7 @@ namespace Notesnook.API.Services Repositories.InboxApiKey.DeleteMany((t) => t.UserId == userId); var result = await unit.Commit(); - await Slogger.Info(nameof(DeleteUserAsync), "User data deleted", userId, result.ToString()); + logger.LogInformation("User data deleted for user {UserId}: {Result}", userId, result); if (!result) throw new Exception("Could not delete user data."); if (!Constants.IS_SELF_HOSTED) @@ -227,7 +218,7 @@ namespace Notesnook.API.Services public async Task DeleteUserAsync(string userId, string jti, string password) { - await Slogger.Info(nameof(DeleteUserAsync), "Deleting user account", userId); + logger.LogInformation("Deleting user account: {UserId}", userId); var userService = await WampServers.IdentityServer.GetServiceAsync(IdentityServerTopics.UserAccountServiceTopic); await userService.DeleteUserAsync(Clients.Notesnook.Id, userId, password); diff --git a/Streetwriters.Common/Logger.cs b/Streetwriters.Common/Logger.cs deleted file mode 100644 index 1edc716..0000000 --- a/Streetwriters.Common/Logger.cs +++ /dev/null @@ -1,52 +0,0 @@ -/* -This file is part of the Notesnook Sync Server project (https://notesnook.com/) - -Copyright (C) 2023 Streetwriters (Private) Limited - -This program is free software: you can redistribute it and/or modify -it under the terms of the Affero GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -Affero GNU General Public License for more details. - -You should have received a copy of the Affero GNU General Public License -along with this program. If not, see . -*/ - -using System; -using System.IO; -using System.Threading.Tasks; - -namespace Streetwriters.Common -{ - public class Slogger - { - public static Task Info(string scope, params string[] messages) - { - return Write(Format("info", scope, messages)); - } - - public static Task Error(string scope, params string[] messages) - { - return Write(Format("error", scope, messages)); - } - private static string Format(string level, string scope, params string[] messages) - { - var date = DateTime.UtcNow.ToString("MM-dd-yyyy HH:mm:ss"); - var messageText = string.Join(" ", messages); - return $"[{date}] | {level} | <{scope}> {messageText}"; - } - private static Task Write(string line) - { - var logDirectory = Path.GetFullPath("./logs"); - if (!Directory.Exists(logDirectory)) - Directory.CreateDirectory(logDirectory); - var path = Path.Join(logDirectory, typeof(T).FullName + "-" + DateTime.UtcNow.ToString("MM-dd-yyyy") + ".log"); - return File.AppendAllLinesAsync(path, new string[1] { line }); - } - } -} \ No newline at end of file diff --git a/Streetwriters.Common/Services/EmailSender.cs b/Streetwriters.Common/Services/EmailSender.cs index 61d1393..a3256fb 100644 --- a/Streetwriters.Common/Services/EmailSender.cs +++ b/Streetwriters.Common/Services/EmailSender.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Text; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using MailKit.Net.Smtp; using MimeKit; using MimeKit.Cryptography; @@ -16,6 +17,12 @@ namespace Streetwriters.Common.Services public class EmailSender : IEmailSender, IAsyncDisposable { private readonly SmtpClient mailClient = new(); + private readonly ILogger logger; + + public EmailSender(ILogger logger) + { + this.logger = logger; + } public async Task SendEmailAsync( string email, @@ -67,7 +74,7 @@ namespace Streetwriters.Common.Services await mailClient.SendAsync(message); } - private static async Task GetEmailBodyAsync( + private async Task GetEmailBodyAsync( EmailTemplate template, IClient client, MailboxAddress sender, @@ -120,7 +127,7 @@ namespace Streetwriters.Common.Services } catch (Exception ex) { - await Slogger.Error("GetEmailBodyAsync", ex.ToString()); + logger.LogError(ex, "Failed to get email body"); return builder.ToMessageBody(); } } diff --git a/Streetwriters.Common/WampServers.cs b/Streetwriters.Common/WampServers.cs index 69feedb..5891a8b 100644 --- a/Streetwriters.Common/WampServers.cs +++ b/Streetwriters.Common/WampServers.cs @@ -55,30 +55,14 @@ namespace Streetwriters.Common public async Task PublishMessageAsync(string topic, V message) { - try - { - IWampRealmProxy channel = await GetChannelAsync(topic); - WampHelper.PublishMessage(channel, topic, message); - } - catch (Exception ex) - { - await Slogger>.Error(nameof(PublishMessageAsync), ex.ToString()); - throw ex; - } + IWampRealmProxy channel = await GetChannelAsync(topic); + WampHelper.PublishMessage(channel, topic, message); } public async Task PublishMessagesAsync(string topic, IEnumerable messages) { - try - { - IWampRealmProxy channel = await GetChannelAsync(topic); - WampHelper.PublishMessages(channel, topic, messages); - } - catch (Exception ex) - { - await Slogger>.Error(nameof(PublishMessagesAsync), ex.ToString()); - throw ex; - } + IWampRealmProxy channel = await GetChannelAsync(topic); + WampHelper.PublishMessages(channel, topic, messages); } } diff --git a/Streetwriters.Identity/Controllers/AccountController.cs b/Streetwriters.Identity/Controllers/AccountController.cs index d7d8093..5de1911 100644 --- a/Streetwriters.Identity/Controllers/AccountController.cs +++ b/Streetwriters.Identity/Controllers/AccountController.cs @@ -32,6 +32,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; +using Microsoft.Extensions.Logging; using Streetwriters.Common; using Streetwriters.Common.Enums; using Streetwriters.Common.Interfaces; @@ -54,13 +55,15 @@ namespace Streetwriters.Identity.Controllers private IPersistedGrantStore PersistedGrantStore { get; set; } private ITokenGenerationService TokenGenerationService { get; set; } private IUserAccountService UserAccountService { get; set; } + private readonly ILogger logger; public AccountController(UserManager _userManager, ITemplatedEmailSender _emailSender, SignInManager _signInManager, RoleManager _roleManager, IPersistedGrantStore store, - ITokenGenerationService tokenGenerationService, IMFAService _mfaService, IUserAccountService userAccountService) : base(_userManager, _emailSender, _signInManager, _roleManager, _mfaService) + ITokenGenerationService tokenGenerationService, IMFAService _mfaService, IUserAccountService userAccountService, ILogger logger) : base(_userManager, _emailSender, _signInManager, _roleManager, _mfaService) { PersistedGrantStore = store; TokenGenerationService = tokenGenerationService; UserAccountService = userAccountService; + this.logger = logger; } [HttpGet("confirm")] @@ -161,7 +164,7 @@ namespace Streetwriters.Identity.Controllers #if (DEBUG || STAGING) return Ok(callbackUrl); #else - await Slogger.Info("ResetUserPassword", user.Email, callbackUrl); + logger.LogInformation("Password reset email sent to: {Email}, callback URL: {CallbackUrl}", user.Email, callbackUrl); await EmailSender.SendPasswordResetEmailAsync(user.Email, callbackUrl, client); return Ok(); #endif diff --git a/Streetwriters.Identity/Controllers/SignupController.cs b/Streetwriters.Identity/Controllers/SignupController.cs index e0b9a93..ba3ae9c 100644 --- a/Streetwriters.Identity/Controllers/SignupController.cs +++ b/Streetwriters.Identity/Controllers/SignupController.cs @@ -26,6 +26,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; +using Microsoft.Extensions.Logging; using Streetwriters.Common; using Streetwriters.Common.Enums; using Streetwriters.Common.Models; @@ -40,9 +41,16 @@ namespace Streetwriters.Identity.Controllers [Route("signup")] public class SignupController : IdentityControllerBase { + private readonly ILogger logger; + private readonly EmailAddressValidator emailValidator; + public SignupController(UserManager _userManager, ITemplatedEmailSender _emailSender, - SignInManager _signInManager, RoleManager _roleManager, IMFAService _mfaService) : base(_userManager, _emailSender, _signInManager, _roleManager, _mfaService) - { } + SignInManager _signInManager, RoleManager _roleManager, IMFAService _mfaService, + ILogger logger, EmailAddressValidator emailValidator) : base(_userManager, _emailSender, _signInManager, _roleManager, _mfaService) + { + this.logger = logger; + this.emailValidator = emailValidator; + } private async Task AddClientRoleAsync(string clientId) { @@ -68,7 +76,7 @@ namespace Streetwriters.Identity.Controllers form.Email = form.Email.ToLowerInvariant(); form.Username = form.Username?.ToLowerInvariant(); - if (!await EmailAddressValidator.IsEmailAddressValidAsync(form.Email)) return BadRequest(new string[] { "Invalid email address." }); + if (!await emailValidator.IsEmailAddressValidAsync(form.Email)) return BadRequest(new string[] { "Invalid email address." }); var result = await UserManager.CreateAsync(new User { @@ -128,7 +136,7 @@ namespace Streetwriters.Identity.Controllers } catch (System.Exception ex) { - await Slogger.Error("Signup", ex.ToString()); + logger.LogError(ex, "Failed to create user account for email: {Email}", form.Email); return BadRequest("Failed to create an account."); } } diff --git a/Streetwriters.Identity/Services/EmailAddressValidator.cs b/Streetwriters.Identity/Services/EmailAddressValidator.cs index b2418d0..610af9e 100644 --- a/Streetwriters.Identity/Services/EmailAddressValidator.cs +++ b/Streetwriters.Identity/Services/EmailAddressValidator.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Streetwriters.Common; using System.Linq; @@ -11,8 +12,14 @@ namespace Streetwriters.Identity.Services { private static DateTimeOffset LAST_FETCH_TIME = DateTimeOffset.MinValue; private static HashSet BLACKLISTED_DOMAINS = new(); + private readonly ILogger logger; - public static async Task IsEmailAddressValidAsync(string email) + public EmailAddressValidator(ILogger logger) + { + this.logger = logger; + } + + public async Task IsEmailAddressValidAsync(string email) { var domain = email.ToLowerInvariant().Split("@")[1]; try @@ -30,7 +37,7 @@ namespace Streetwriters.Identity.Services } catch (Exception ex) { - await Slogger.Error("IsEmailAddressValidAsync", ex.ToString()); + logger.LogError(ex, "Failed to validate email address: {Email}", email); return BLACKLISTED_DOMAINS.Count > 0 ? !BLACKLISTED_DOMAINS.Contains(domain) : true; } } diff --git a/Streetwriters.Identity/Services/MFAService.cs b/Streetwriters.Identity/Services/MFAService.cs index f96d06d..de423dc 100644 --- a/Streetwriters.Identity/Services/MFAService.cs +++ b/Streetwriters.Identity/Services/MFAService.cs @@ -24,6 +24,7 @@ using System.Text; using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; using Streetwriters.Common; using Streetwriters.Common.Enums; using Streetwriters.Common.Interfaces; @@ -42,11 +43,13 @@ namespace Streetwriters.Identity.Services private UserManager UserManager { get; set; } private ITemplatedEmailSender EmailSender { get; set; } private ISMSSender SMSSender { get; set; } - public MFAService(UserManager _userManager, ITemplatedEmailSender emailSender, ISMSSender smsSender) + private readonly ILogger logger; + public MFAService(UserManager _userManager, ITemplatedEmailSender emailSender, ISMSSender smsSender, ILogger logger) { UserManager = _userManager; EmailSender = emailSender; SMSSender = smsSender; + this.logger = logger; } public async Task EnableMFAAsync(User user, string primaryMethod) @@ -186,7 +189,7 @@ namespace Streetwriters.Identity.Services case "sms": await UserManager.SetPhoneNumberAsync(user, form.PhoneNumber); var id = await SMSSender.SendOTPAsync(form.PhoneNumber, client); - await Slogger.Info("SendOTPAsync", user.Id.ToString(), id); + logger.LogInformation("SMS OTP sent for user: {UserId}, SMS ID: {SmsId}", user.Id, id); await this.ReplaceClaimAsync(user, MFAService.SMS_ID_CLAIM, id); break;