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
|
||||
@@ -76,6 +79,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity to insert.</param>
|
||||
/// <exception cref="Exception">Throws and re-throws exceptions after logging.</exception>
|
||||
/// <!-- aidoc:v1 sig=c7a7ad8 body=26b3581 -->
|
||||
public override async Task InsertOneAsync(T entity)
|
||||
{
|
||||
try
|
||||
@@ -94,6 +98,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 +118,10 @@ 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=high kind=wrong_summary
|
||||
/// "Summary says 'Updates an existing' entity, but IsUpsert = true means the method will also insert the document if it does not already exist, so 'existing' is contradicted by the code." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=stale_summary
|
||||
/// "The phrase 'master list entity' is not supported by the code, which is generic over T and contains no reference to a master list; the term appears to be carried over from a different/specialized method." -->
|
||||
public async Task Update(T entity)
|
||||
{
|
||||
try
|
||||
@@ -133,6 +142,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 +176,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
|
||||
/// "Summary says 'master list entity' but the method is generic on type T, not specifically MasterList." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
|
||||
/// "Returns tag says 'The MasterList entity' but the method returns Task<T?> for a generic type T." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "Documents <exception cref='Exception'> but the catch block swallows exceptions and returns null; the method does not throw." -->
|
||||
public async Task<T?> FindById(ObjectId id)
|
||||
{
|
||||
try
|
||||
@@ -197,6 +213,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 body in a try-catch that catches all Exception instances and returns null; no exception is ever thrown to the caller, so the <exception cref=\"Exception\"> tag is misleading." -->
|
||||
public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId, LocaleEnum locale)
|
||||
{
|
||||
try
|
||||
@@ -342,6 +360,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 +393,10 @@ 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-review:v1 severity=medium kind=extra_exception
|
||||
/// "The <exception cref=\"Exception\"/> tag indicates the method can throw Exception, but the body catches all Exception and returns null, so it never throws." -->
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=wrong_returns
|
||||
/// "Returns Task<T?> generically, but the doc describes the return as 'The MasterList entity'. The actual generic type is not constrained to MasterList." -->
|
||||
public async Task<T?> FindById(ObjectId id, LocaleEnum? locale)
|
||||
{
|
||||
try
|
||||
@@ -556,6 +579,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_summary
|
||||
/// "Summary describes a 'master list entity' but the method is generic over type T and is not specific to master lists." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
|
||||
/// "Documents the return as 'The MasterList entity' but the method returns Task<T?> where T is a generic type parameter." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
|
||||
/// "The method's try/catch catches every Exception and returns null, so no Exception is propagated to callers; the <exception> tag misrepresents the behavior." -->
|
||||
public async Task<T?> FindByName(string name)
|
||||
{
|
||||
try
|
||||
@@ -584,6 +613,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 +624,10 @@ 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_summary
|
||||
/// "The summary states the method 'retrieves paginated master lists', but the method does not perform any pagination (no Skip/Limit calls) and does not 'retrieve' results—it only builds a fluent query. The actual pagination would need to be applied by the caller on the returned IFindFluent." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
|
||||
/// "The returns description says 'A fluent queryable for MasterList results', but the method's return type is IFindFluent<T, T>—a generic fluent queryable, not specific to MasterList. The type parameter T is not constrained to MasterList." -->
|
||||
public IFindFluent<T, T> GetPaginatedMasterList(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<T>.Filter;
|
||||
@@ -621,6 +655,8 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
|
||||
/// <param name="filter">The pagination and filtering parameters.</param>
|
||||
/// <param name="listId">The ObjectId of the master list.</param>
|
||||
/// <returns>A list of filtered OptionList items.</returns>
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
|
||||
/// "Summary states the method 'retrieves paginated options', but the code performs no pagination (no Skip/Take); only the filter's text is applied, and all matching options are returned via .ToList()." -->
|
||||
public async Task<List<OptionList>> GetPaginatedOptions(PaginationFilter filter, ObjectId listId)
|
||||
{
|
||||
//TODO: LOCALE
|
||||
@@ -646,6 +682,10 @@ 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=medium kind=wrong_returns
|
||||
/// "The <returns> description states null is returned 'if duplicate exists', but null is also returned when UpdateOneAsync's ModifiedCount == 0 (e.g., document not found) and when an exception is caught, not solely on duplicate." -->
|
||||
/// <!-- aidoc-review:v1 severity=medium kind=wrong_exception
|
||||
/// "<exception cref=\"Exception\"> describes logging and returning null, but the code catches the exception from UpdateOneAsync rather than letting it propagate. Other parts of the method (e.g., GetMasterListByIdAndSearchOptions, FindById) are not wrapped in try/catch and could throw unhandled exceptions." -->
|
||||
public async Task<OptionList?> AddOptionToMasterList(ObjectId id, FilterOptionListElement opt)
|
||||
{
|
||||
var exist = await GetMasterListByIdAndSearchOptions(id, opt);
|
||||
@@ -689,6 +729,8 @@ 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=extra_exception
|
||||
/// "The method catches all exceptions internally and returns an empty list; it does not throw Exception to callers, so the <exception cref=\"Exception\"/> tag is misleading." -->
|
||||
public async Task<IEnumerable<T>> GetAll()
|
||||
{
|
||||
try
|
||||
@@ -708,6 +750,10 @@ 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 <exception cref=\"Exception\"> tag implies the method throws Exception, but the body catches all exceptions and returns an empty list — it never propagates." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
|
||||
/// "Summary says 'Retrieves all master list entities without options', which reads as filtering for entities that have no options, but the code uses FilterDefinition<T>.Empty (no filter) and returns all entities with Options reduced to a count." -->
|
||||
public async Task<IEnumerable<MasterListDto>> GetAllWithoutOptions()
|
||||
{
|
||||
try
|
||||
@@ -736,6 +782,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=extra_exception
|
||||
/// "The method catches all exceptions internally and returns 0, so it does not propagate Exception to callers. The <exception cref=\"Exception\"/> tag is misleading." -->
|
||||
public async Task<int> Count()
|
||||
{
|
||||
try
|
||||
@@ -758,6 +806,7 @@ 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:v1 sig=f6ee5be body=17d6a96 -->
|
||||
public async Task<List<OptionList>> GetMasterListByIdAndSearchOptions(ObjectId id, FilterOptionListElement? filters)
|
||||
{
|
||||
try
|
||||
@@ -973,6 +1022,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 +1123,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 +1159,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 +1184,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 method catches and handles Exception internally (returning null) rather than throwing it; the <exception cref=\"Exception\"> tag is therefore incorrect since no exception is propagated to the caller." -->
|
||||
public async Task<UpdateMasterListDetailsDto?> UpdateOptionDetailsToMasterList(ObjectId id,
|
||||
UpdateMasterListDetailsDto opt)
|
||||
{
|
||||
@@ -1167,6 +1221,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=medium kind=extra_exception
|
||||
/// "The method catches all exceptions in a try/catch and returns false; it never throws Exception to the caller, so the <exception cref=\"Exception\"> tag is incorrect." -->
|
||||
public async Task<bool> UpdateMasterListName(ObjectId id, string name)
|
||||
{
|
||||
var filter = Builders<T>.Filter.And(
|
||||
@@ -1193,6 +1249,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=medium kind=extra_exception
|
||||
/// "The <exception cref=\"Exception\"/> tag implies the method throws, but the catch block handles all exceptions internally and the method never rethrows; the tag is misleading and should be removed." -->
|
||||
public async Task<bool> UpdateMasterListDescription(ObjectId id, string description)
|
||||
{
|
||||
var filter = Builders<T>.Filter.And(
|
||||
@@ -1219,6 +1277,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=high kind=wrong_exception
|
||||
/// "The method catches all Exception types and returns false; it does not throw Exception, so listing it as a thrown exception is misleading." -->
|
||||
public async Task<bool> RemoveMasterListOption(ObjectId id, OptionList oldOpt)
|
||||
{
|
||||
var filter = Builders<T>.Filter.Eq("_id", id);
|
||||
@@ -1250,6 +1310,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 claims 'text indexes' are created, but the code uses Builders<T>.IndexKeys.Ascending(...), which creates regular ascending B-tree indexes, not text indexes." -->
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
if (typeof(T) == typeof(DiagnosisList))
|
||||
@@ -1275,6 +1337,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 +1350,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 +1428,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 summary states the method creates a query 'for paginated results', but the code contains no pagination logic (no Skip/Limit calls); it only applies a combined filter and sort before returning the IFindFluent." -->
|
||||
private IFindFluent<T, T> CreateFindFluent(List<FilterDefinition<T>> filters, SortDefinition<T> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
@@ -1379,6 +1445,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
|
||||
/// "Summary states 'Creates LocaleItem entries for all locales except the specified default' but the code also explicitly excludes the LocaleEnum.Default value in addition to the localeList parameter, so two locales are skipped, not one." -->
|
||||
private Locale GetNewItemLocale(LocaleEnum localeList, string opt)
|
||||
{
|
||||
var newLocale = new Locale();
|
||||
@@ -1418,6 +1486,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 +1528,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=medium kind=extra_exception
|
||||
/// "The method catches all exceptions internally (catch (Exception ex)) and returns an empty list; no exceptions are propagated, so documenting <exception cref=\"Exception\"> is misleading." -->
|
||||
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,7 @@ 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:v1 sig=bdfb451 body=e3fc1ac -->
|
||||
public async Task<User> Login(string username, string password)
|
||||
{
|
||||
if (_ldapConfig.Server == null)
|
||||
@@ -159,6 +162,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=high kind=wrong_returns
|
||||
/// "The method returns Task<User> but the documentation only says 'A task representing the asynchronous operation' without mentioning the User return type, misleading readers about the actual return contract." -->
|
||||
public Task<User> Login(HttpContext context)
|
||||
=> throw new LoginServicesException("Not implemented");
|
||||
|
||||
@@ -169,6 +174,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 <returns> tag says 'A task representing the asynchronous operation' but the method returns Task<User>; the documented return type omits the User result." -->
|
||||
public Task<User> Authenticate(string username, string password)
|
||||
=> throw new LoginServicesException("Not implemented");
|
||||
|
||||
@@ -178,6 +185,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 +195,8 @@ 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-review:v1 severity=medium kind=missing_returns
|
||||
/// "The method returns Task<User?>, but the <returns> description only says 'A task representing the asynchronous operation' without mentioning the User? result type." -->
|
||||
public Task<User?> GetByEmail(string email)
|
||||
=> throw new LoginServicesException("Not implemented");
|
||||
|
||||
@@ -196,6 +206,8 @@ 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-review:v1 severity=low kind=missing_returns
|
||||
/// "The <returns> description 'A task representing the asynchronous operation' omits the User? type that the Task would contain, as declared in the method signature Task<User?>." -->
|
||||
public Task<User?> GetByUsername(string username)
|
||||
=> throw new LoginServicesException("Not implemented");
|
||||
|
||||
@@ -204,6 +216,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 +228,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 +253,7 @@ 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:v1 sig=d2bafd5 body=4af15eb -->
|
||||
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
|
||||
/// "Summary describes retrieving a list of authorities and mapping LDAP groups to authorities, but the method actually constructs a User object with UserName, first name, and last name from LDAP attributes." -->
|
||||
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
|
||||
/// "Returns description states 'The existing or newly created user with updated authorities', but the method always creates a new User with name information and never deals with authorities or existing users." -->
|
||||
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