docs(iec62304): [REL-1.0.2] validate and curate XML doc review markers
This commit is contained in:
@@ -20,6 +20,7 @@ namespace adas_core.Infrastructure.Repositories;
|
||||
/// options lists, diagnoses, allergies, procedures, treatments, and other reference data.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of MasterList entity to manage.</typeparam>
|
||||
/// <!-- aidoc:v1 sig=f958de2 -->
|
||||
public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository<T> where T : MasterList
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
@@ -30,6 +31,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="apiSettings">API settings containing collection names configuration.</param>
|
||||
/// <param name="database">The MongoDB database instance.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when apiSettings is null.</exception>
|
||||
/// <!-- aidoc:v1 sig=800d538 body=d2b18a3 -->
|
||||
public MasterListRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
@@ -41,6 +43,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// Maps different MasterList subtypes to their corresponding MongoDB collection names.
|
||||
/// </summary>
|
||||
/// <returns>The collection name for the current MasterList type.</returns>
|
||||
/// <!-- aidoc:v1 sig=94e22ff body=64e6c55 -->
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return typeof(T) switch
|
||||
@@ -94,6 +97,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// </summary>
|
||||
/// <param name="id">The ObjectId of the entity to delete.</param>
|
||||
/// <exception cref="Exception">Throws and re-throws exceptions after logging.</exception>
|
||||
/// <!-- aidoc:v1 sig=3de1ad6 body=fe0ba8c -->
|
||||
public async Task Delete(ObjectId id)
|
||||
{
|
||||
try
|
||||
@@ -113,6 +117,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity with updated values.</param>
|
||||
/// <exception cref="Exception">Throws and re-throws exceptions after logging.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=wrong_summary
|
||||
/// "Summary says 'Updates an existing' entity, but the code uses IsUpsert = true, so the method can also insert a new entity when one does not exist." -->
|
||||
public async Task Update(T entity)
|
||||
{
|
||||
try
|
||||
@@ -133,6 +139,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="id">The ObjectId of the master list.</param>
|
||||
/// <param name="newOpt">The OptionList with updated values.</param>
|
||||
/// <returns>The updated OptionList if found; otherwise, null.</returns>
|
||||
/// <!-- aidoc:v1 sig=64ca4dd body=a7714e6 -->
|
||||
public async Task<OptionList?> UpdateFullMasterListOption(ObjectId id, OptionList newOpt)
|
||||
{
|
||||
var filter = Builders<T>.Filter.Where(o => o.Id == id && o.Options.Any(opt => opt.Id == newOpt.Id)
|
||||
@@ -166,6 +173,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="id">The ObjectId of the entity to retrieve.</param>
|
||||
/// <returns>The MasterList entity if found; otherwise, null.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
|
||||
/// "Method is generic (FindById<T>) and not specific to a 'master list entity'; summary incorrectly scopes it to master list." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
|
||||
/// "Documentation says 'The MasterList entity' but the method's return type is the generic T?, not a MasterList." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "Documents <exception cref=\"Exception\">, but the method catches all exceptions internally and never propagates them to the caller." -->
|
||||
public async Task<T?> FindById(ObjectId id)
|
||||
{
|
||||
try
|
||||
@@ -197,6 +210,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="locale">The locale for translation.</param>
|
||||
/// <returns>The OptionList with translated fields if found; otherwise, null.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
|
||||
/// "The method wraps its entire body in a try/catch that catches Exception, logs it, and returns null; it never propagates Exception to the caller, so the <exception cref=\"Exception\"/> tag is misleading. The behavior described (log and return null) belongs in the <remarks> or summary, not as a thrown exception." -->
|
||||
public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId, LocaleEnum locale)
|
||||
{
|
||||
try
|
||||
@@ -342,6 +357,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="optionId">The ObjectId of the option to retrieve.</param>
|
||||
/// <returns>The OptionList if found; otherwise, null.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
|
||||
/// <!-- aidoc:v1 sig=ccc34cb body=71837cc -->
|
||||
public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId)
|
||||
{
|
||||
try
|
||||
@@ -374,6 +390,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="locale">Optional locale for translated option names.</param>
|
||||
/// <returns>The MasterList entity with translated options if found; otherwise, null.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
|
||||
/// <!-- aidoc:v1 sig=cb4a658 body=f2e88d8 -->
|
||||
public async Task<T?> FindById(ObjectId id, LocaleEnum? locale)
|
||||
{
|
||||
try
|
||||
@@ -556,6 +573,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="name">The name of the master list to retrieve.</param>
|
||||
/// <returns>The MasterList entity if found; otherwise, null.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
|
||||
/// "The method returns Task<T?> (generic), not MasterList; the return type description should reference T, not MasterList." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
|
||||
/// "Summary says 'Finds a master list entity' but the method is generic (T) and is not specific to master lists." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "The method catches all exceptions internally and returns null; it does not propagate any exception, so the <exception> tag is misleading." -->
|
||||
public async Task<T?> FindByName(string name)
|
||||
{
|
||||
try
|
||||
@@ -584,6 +607,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="id">The ObjectId of the master list.</param>
|
||||
/// <param name="textSearch">Optional text to search within options.</param>
|
||||
/// <returns>A list of matching OptionList items.</returns>
|
||||
/// <!-- aidoc:v1 sig=569d223 body=bb7f2c6 -->
|
||||
public async Task<List<OptionList>> GetMasterListByIdAndTextSearchContaining(ObjectId id, string? textSearch)
|
||||
{
|
||||
return await GetOptionsByTextSearch(textSearch, id);
|
||||
@@ -594,6 +618,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// </summary>
|
||||
/// <param name="filter">The pagination and filtering parameters.</param>
|
||||
/// <returns>A fluent queryable for MasterList results.</returns>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
|
||||
/// "Documentation states the method returns 'A fluent queryable for MasterList results', but the method returns IFindFluent<T, T> where T is a generic type parameter, not specifically MasterList." -->
|
||||
public IFindFluent<T, T> GetPaginatedMasterList(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<T>.Filter;
|
||||
@@ -646,6 +672,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="opt">The option element to add.</param>
|
||||
/// <returns>The newly created OptionList if successful; otherwise, null if duplicate exists.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "<exception cref=\"Exception\"> documents an exception that is caught and handled inside the method (try/catch returns null) rather than thrown out to the caller." -->
|
||||
public async Task<OptionList?> AddOptionToMasterList(ObjectId id, FilterOptionListElement opt)
|
||||
{
|
||||
var exist = await GetMasterListByIdAndSearchOptions(id, opt);
|
||||
@@ -689,6 +717,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// </summary>
|
||||
/// <returns>An enumerable of all MasterList entities.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
|
||||
/// "Method is generic (IEnumerable<T>), not specific to 'master list entities'; the name 'master list' does not appear in the code." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
|
||||
/// "Documents 'An enumerable of all MasterList entities' but the method is generic and returns IEnumerable<T>, not a concrete MasterList type." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "Documents <exception cref='Exception'> but the method catches all exceptions internally and returns an empty list; it does not throw Exception." -->
|
||||
public async Task<IEnumerable<T>> GetAll()
|
||||
{
|
||||
try
|
||||
@@ -708,6 +742,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// </summary>
|
||||
/// <returns>An enumerable of MasterListDto containing id, name, description, listType, and options count.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "The method catches all exceptions in a try/catch and returns an empty list without rethrowing, so it does not throw Exception. The <exception> tag misleads readers into expecting an exception to propagate." -->
|
||||
public async Task<IEnumerable<MasterListDto>> GetAllWithoutOptions()
|
||||
{
|
||||
try
|
||||
@@ -736,6 +772,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// </summary>
|
||||
/// <returns>The total count of entities.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns 0 on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "The method catches all exceptions and returns 0, so it never throws Exception. The <exception cref=\"Exception\"> tag misleads readers into thinking the method can throw." -->
|
||||
public async Task<int> Count()
|
||||
{
|
||||
try
|
||||
@@ -758,6 +796,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="filters">The filter criteria including text, name, description, and optionType.</param>
|
||||
/// <returns>A list of matching OptionList items ordered by name.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
|
||||
/// "The method has a catch (Exception ex) block that logs and returns an empty list; it does not propagate any exception to callers, making the <exception cref='Exception'> tag misleading." -->
|
||||
public async Task<List<OptionList>> GetMasterListByIdAndSearchOptions(ObjectId id, FilterOptionListElement? filters)
|
||||
{
|
||||
try
|
||||
@@ -973,6 +1013,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="locale">The locale for translation updates.</param>
|
||||
/// <returns>The updated OptionList if successful; otherwise, null.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
|
||||
/// <!-- aidoc:v1 sig=e771f23 body=5520a4a -->
|
||||
public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt, LocaleEnum locale)
|
||||
{
|
||||
// 1. Evitar duplicados
|
||||
@@ -1073,6 +1114,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="newOpt">The OptionList with updated values.</param>
|
||||
/// <returns>The updated OptionList if successful; otherwise, null.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
|
||||
/// <!-- aidoc:v1 sig=6def54c body=9554543 -->
|
||||
public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt)
|
||||
{
|
||||
var master = await FindById(id);
|
||||
@@ -1108,6 +1150,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="id">The ObjectId of the master list.</param>
|
||||
/// <param name="deleteOptId">The ObjectId of the option to delete.</param>
|
||||
/// <returns>True if the option was deleted; otherwise, false.</returns>
|
||||
/// <!-- aidoc:v1 sig=e663f16 body=75627bc -->
|
||||
public async Task<bool> DeleteMasterListOption(ObjectId id, ObjectId deleteOptId)
|
||||
{
|
||||
// Define el filtro para encontrar el documento por su _id
|
||||
@@ -1132,6 +1175,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="opt">The UpdateMasterListDetailsDto with updated values.</param>
|
||||
/// <returns>The updated UpdateMasterListDetailsDto if successful; otherwise, null.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
|
||||
/// "The <exception cref=\"Exception\"> tag suggests the method may throw Exception, but the body catches all exceptions internally, logs them, and returns null without rethrowing." -->
|
||||
public async Task<UpdateMasterListDetailsDto?> UpdateOptionDetailsToMasterList(ObjectId id,
|
||||
UpdateMasterListDetailsDto opt)
|
||||
{
|
||||
@@ -1167,6 +1212,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="name">The new name.</param>
|
||||
/// <returns>True if the update was successful; otherwise, false.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns false on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "The <exception cref=\"Exception\"> tag documents an exception that is never thrown. The method's try/catch block catches all Exception types and returns false, so callers do not need to handle any exception thrown by this method." -->
|
||||
public async Task<bool> UpdateMasterListName(ObjectId id, string name)
|
||||
{
|
||||
var filter = Builders<T>.Filter.And(
|
||||
@@ -1193,6 +1240,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="description">The new description.</param>
|
||||
/// <returns>True if the update was successful; otherwise, false.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns false on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "The method catches all exceptions and returns false rather than throwing them, so an <exception> tag documenting that exceptions are thrown is misleading." -->
|
||||
public async Task<bool> UpdateMasterListDescription(ObjectId id, string description)
|
||||
{
|
||||
var filter = Builders<T>.Filter.And(
|
||||
@@ -1219,6 +1268,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="oldOpt">The OptionList to remove.</param>
|
||||
/// <returns>True if the option was removed; otherwise, false.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns false on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
|
||||
/// "The method catches all exceptions internally and returns false rather than propagating them, so an <exception> tag is misleading." -->
|
||||
public async Task<bool> RemoveMasterListOption(ObjectId id, OptionList oldOpt)
|
||||
{
|
||||
var filter = Builders<T>.Filter.Eq("_id", id);
|
||||
@@ -1250,6 +1301,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// Creates necessary indexes for the MasterList collection.
|
||||
/// Currently creates text indexes for DiagnosisList on options.name, options.description, and options._id.
|
||||
/// </summary>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
|
||||
/// "Documentation states the method 'creates text indexes', but the code uses Builders<T>.IndexKeys.Ascending(...) to create ascending indexes, not text indexes. The language options (LanguageOverride/DefaultLanguage) are configured, but no Text index keys are used." -->
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
if (typeof(T) == typeof(DiagnosisList))
|
||||
@@ -1275,6 +1328,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// </summary>
|
||||
/// <param name="textSearch">Optional text to search within options.</param>
|
||||
/// <returns>A list of matching OptionList items.</returns>
|
||||
/// <!-- aidoc:v1 sig=484b092 body=48e3496 -->
|
||||
public async Task<List<OptionList>> GetMasterListByTextSearch(string? textSearch)
|
||||
{
|
||||
return await GetOptionsByTextSearch(textSearch);
|
||||
@@ -1287,6 +1341,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="id">Optional master list ObjectId to filter results.</param>
|
||||
/// <returns>A list of matching OptionList items ordered by name.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
|
||||
/// <!-- aidoc:v1 sig=6ebeac8 body=1d7bbb7 -->
|
||||
private async Task<List<OptionList>> GetOptionsByTextSearch(string? textSearch, ObjectId? id = null)
|
||||
{
|
||||
try
|
||||
@@ -1364,6 +1419,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="filters">List of filter definitions to apply.</param>
|
||||
/// <param name="sort">Sort definition for the query results.</param>
|
||||
/// <returns>A fluent queryable for T results.</returns>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
|
||||
/// "The method does not perform pagination (no Skip/Limit applied). It only combines filters and applies a sort, so 'paginated results' in the summary is incorrect." -->
|
||||
private IFindFluent<T, T> CreateFindFluent(List<FilterDefinition<T>> filters, SortDefinition<T> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
@@ -1379,6 +1436,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="localeList">The default locale to exclude from translations.</param>
|
||||
/// <param name="opt">The option name to use as default translation.</param>
|
||||
/// <returns>A Locale object with translations for all other locales.</returns>
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=wrong_summary
|
||||
/// "The summary says entries are created for 'all locales except the specified default', but the code also always excludes LocaleEnum.Default (hardcoded skip) in addition to the localeList parameter, which is not mentioned." -->
|
||||
private Locale GetNewItemLocale(LocaleEnum localeList, string opt)
|
||||
{
|
||||
var newLocale = new Locale();
|
||||
@@ -1418,6 +1477,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// </summary>
|
||||
/// <param name="input">The input string to build the pattern from.</param>
|
||||
/// <returns>A regex-compatible pattern string.</returns>
|
||||
/// <!-- aidoc:v1 sig=2992c00 body=ae88daf -->
|
||||
private static string BuildRegexPattern(string input)
|
||||
{
|
||||
var regexPattern = new StringBuilder();
|
||||
@@ -1459,6 +1519,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="locale">The locale for translation.</param>
|
||||
/// <returns>A list of matching OptionList items ordered by name.</returns>
|
||||
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=low kind=extra_exception
|
||||
/// "The method catches all exceptions internally and returns an empty list; the <exception cref=\"Exception\"> tag is misleading because the method does not actually throw any exception to the caller." -->
|
||||
private async Task<List<OptionList>> GetMasterListByIdAndTextSearch(
|
||||
ObjectId id, string newOptName, LocaleEnum locale)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace adas_core.LdapLogin;
|
||||
/// The service also handles the creation of new users in the application if they do not already exist, based on the LDAP information.
|
||||
/// It uses configuration settings for connecting to the LDAP server and for mapping LDAP attributes to user properties and authorities.
|
||||
/// </summary>
|
||||
/// <!-- aidoc:v1 sig=4e5637f -->
|
||||
public class LdapLoginService : ILoginService
|
||||
{
|
||||
/// <summary>
|
||||
@@ -51,6 +52,7 @@ public class LdapLoginService : ILoginService
|
||||
/// <param name="userService">The user service for managing user information.</param>
|
||||
/// <param name="authorityService">The authority service for managing user authorities.</param>
|
||||
/// <param name="logger">The logger for logging LDAP login operations.</param>
|
||||
/// <!-- aidoc:v1 sig=f1b8e4e body=6c4718f -->
|
||||
public LdapLoginService(
|
||||
IOptions<LdapConfig> ldapConfig,
|
||||
IValidator<LdapConfig> validator,
|
||||
@@ -83,6 +85,8 @@ public class LdapLoginService : ILoginService
|
||||
/// <returns>The authenticated user.</returns>
|
||||
/// <exception cref="LoginServicesException">Thrown when there is an error during the login process.</exception>
|
||||
/// <exception cref="UserNotFoundException">Thrown when the user is not found in the LDAP directory.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "UserNotFoundException is documented as thrown 'when the user is not found in the LDAP directory', but the code actually throws it from the catch (LdapException) block during the bind operation. The 'user not found in directory' case (empty search result) throws LoginServicesException, not UserNotFoundException." -->
|
||||
public async Task<User> Login(string username, string password)
|
||||
{
|
||||
if (_ldapConfig.Server == null)
|
||||
@@ -159,6 +163,8 @@ public class LdapLoginService : ILoginService
|
||||
/// <param name="context">The HTTP context of the request.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
/// <exception cref="LoginServicesException">Thrown when the method is not implemented.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=missing_returns
|
||||
/// "The <returns> description says 'A task representing the asynchronous operation' but the method returns Task<User>; the User element of the return type is not documented." -->
|
||||
public Task<User> Login(HttpContext context)
|
||||
=> throw new LoginServicesException("Not implemented");
|
||||
|
||||
@@ -169,6 +175,8 @@ public class LdapLoginService : ILoginService
|
||||
/// <param name="password">The password of the user to authenticate.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
/// <exception cref="LoginServicesException">Thrown when the method is not implemented.</exception>
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=wrong_returns
|
||||
/// "The method returns Task<User>, but the documentation only states 'A task representing the asynchronous operation' without mentioning that the task produces a User." -->
|
||||
public Task<User> Authenticate(string username, string password)
|
||||
=> throw new LoginServicesException("Not implemented");
|
||||
|
||||
@@ -178,6 +186,7 @@ public class LdapLoginService : ILoginService
|
||||
/// <param name="id">The ID of the user to retrieve.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
/// <exception cref="LoginServicesException">Thrown when the method is not implemented.</exception>
|
||||
/// <!-- aidoc:v1 sig=877a869 -->
|
||||
public Task<User?> GetById(ObjectId id)
|
||||
=> throw new LoginServicesException("Not implemented");
|
||||
|
||||
@@ -187,6 +196,7 @@ public class LdapLoginService : ILoginService
|
||||
/// <param name="email">The email of the user to retrieve.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
/// <exception cref="LoginServicesException">Thrown when the method is not implemented.</exception>
|
||||
/// <!-- aidoc:v1 sig=ba92b09 -->
|
||||
public Task<User?> GetByEmail(string email)
|
||||
=> throw new LoginServicesException("Not implemented");
|
||||
|
||||
@@ -196,6 +206,7 @@ public class LdapLoginService : ILoginService
|
||||
/// <param name="username">The username of the user to retrieve.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
/// <exception cref="LoginServicesException">Thrown when the method is not implemented.</exception>
|
||||
/// <!-- aidoc:v1 sig=5184c30 -->
|
||||
public Task<User?> GetByUsername(string username)
|
||||
=> throw new LoginServicesException("Not implemented");
|
||||
|
||||
@@ -204,6 +215,7 @@ public class LdapLoginService : ILoginService
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
/// <exception cref="LoginServicesException">Thrown when the method is not implemented.</exception>
|
||||
/// <!-- aidoc:v1 sig=aa066d6 -->
|
||||
public Task<List<User>> GetAllUsers()
|
||||
=> throw new LoginServicesException("Not implemented");
|
||||
|
||||
@@ -215,6 +227,7 @@ public class LdapLoginService : ILoginService
|
||||
/// <param name="userEntryLdap">The user information obtained from the LDAP entry.</param>
|
||||
/// <param name="entry">The LDAP entry containing the user's information.</param>
|
||||
/// <returns>The existing or newly created user with updated authorities.</returns>
|
||||
/// <!-- aidoc:v1 sig=87de1c2 body=a43bebd -->
|
||||
private async Task<User?> GetOrCreateUser(User userEntryLdap, LdapEntry entry)
|
||||
|
||||
{
|
||||
@@ -239,6 +252,8 @@ public class LdapLoginService : ILoginService
|
||||
/// <param name="user">The user whose authorities are being checked.</param>
|
||||
/// <param name="entry">The LDAP entry containing the user's information.</param>
|
||||
/// <returns>A list of updated authorities for the user.</returns>
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=stale_summary
|
||||
/// "Summary states the method 'checks' authorities, but the method actually synchronizes authorities: it updates existing entries (when CanUpdate is true) and inserts new ones via _authorityService, with side effects beyond a read-only check." -->
|
||||
private async Task<List<Authorization>> CheckAuthorities(User user, LdapEntry entry)
|
||||
|
||||
{
|
||||
@@ -289,6 +304,7 @@ public class LdapLoginService : ILoginService
|
||||
/// <param name="entry">The LDAP entry containing the user's information.</param>
|
||||
/// <param name="user">The user whose authorities are being retrieved.</param>
|
||||
/// <returns>A list of authorities for the user based on the whitelist.</returns>
|
||||
/// <!-- aidoc:v1 sig=a8263f0 body=9e6cc38 -->
|
||||
private List<Authorization> GetAuthoritiesWhiteList(LdapEntry entry, User user)
|
||||
|
||||
{
|
||||
@@ -331,6 +347,10 @@ public class LdapLoginService : ILoginService
|
||||
/// </summary>
|
||||
/// <param name="ldapEntry">The LDAP entry containing the user's information.</param>
|
||||
/// <returns>The existing or newly created user with updated authorities.</returns>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
|
||||
/// "The summary claims the method retrieves a list of authorities and maps LDAP groups to authorities, but the method actually constructs a User object using username, first name, and last name properties from the LDAP entry." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
|
||||
/// "The <returns> tag claims to return an 'existing or newly created user with updated authorities', but the method always creates a new User and never touches authorities." -->
|
||||
private User GetUser(LdapEntry ldapEntry)
|
||||
|
||||
{
|
||||
@@ -365,6 +385,7 @@ public class LdapLoginService : ILoginService
|
||||
/// <param name="ldapEntry">The LDAP entry containing the user's information.</param>
|
||||
/// <param name="user">The user whose authorities are being retrieved.</param>
|
||||
/// <returns>A list of authorities for the user based on the LDAP entry and the application's configuration.</returns>
|
||||
/// <!-- aidoc:v1 sig=1e1f0f2 body=18015c0 -->
|
||||
private List<Authorization> GetAuthoritiesMap(LdapEntry ldapEntry, User user)
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user