GroupImageRepository¶
âš High-severity security finding (SC-SDN-01):
GetFilteredImageGroups' deleted-image filter is inverted relative to the deletion convention used elsewhere in the codebase. See Behavioral notes and Security and authorization before relying on this method for access control.
GroupImageRepository is the RepositoryBase<ImageGroup> implementation backing group image search and soft-delete, and it is the subject of this library's highest-severity security finding: its in-memory deleted-image filter (ImageDeleteCode != null || CanUserSeeDeletedImages) is inverted, so users without the GroupImagingDeleted permission are shown soft-deleted images while never-deleted images with a null delete code are hidden (SC-SDN-01, Security and authorization). Both visibility filters (deleted and confidential) run in memory after ToList(), so every image in scope is loaded into the process before filtering (SC-SDN-02).
Purpose¶
- Retrieve a single
ImageGroupby id, with existence-check helpers (ImageFound,GetImageGroupOrDefault). - Soft-delete an image by setting its
ImageDeleteCodeto"Y"and stamping the update user/date, only if it is not already deleted, per SDN-BR-040. - Search group images by group/parent group, category, document type, create user, and date range, applying sentinel-value "no filter" semantics (SDN-BR-041) and deleted/confidential visibility rules (SDN-BR-042, SDN-BR-043) — subject to the SC-SDN-01 inversion noted above.
Context¶
- Namespace:
SAIF.Data.NHibernate.Repositories.Groups - Assembly/package:
SAIF.Data.NHibernate(ships inside theSAIF.SAIFCode.CoreNuGet package) - Base class:
RepositoryBase<ImageGroup>fromSAIF.Framework.Data.NHibernate(external, resolved via Legends CLI — see Inherited public members below). - Implements:
IGroupImageRepository, defined inSAIF.Data.Interfaces.Repositories.Groups.
Public members¶
| Member | Signature | Purpose |
|---|---|---|
| GroupImageRepository(NHibernateUnitOfWork) | public GroupImageRepository(NHibernateUnitOfWork uow) |
Constructor; passes uow to the RepositoryBase<ImageGroup> base. |
| ImageFound | public bool ImageFound(long groupImageId) |
Returns true if an ImageGroup with the given id exists, by calling GetImageGroupOrDefault and checking for a non-null result (SQL-022). |
| Delete | public void Delete(ImageDelete imageDelete) |
Loads the ImageGroup for imageDelete.ImageGroupId; if its Image.ImageDeleteCode is blank/null/" ", sets it to "Y" and stamps UpdateUser/UpdateDate from imageDelete. No-op (does not re-stamp) if already marked deleted (SDN-BR-040, SQL-054). Does not check CanUserEditImages; enforcement is expected in the caller (SC-SDN-06, Security and authorization). |
| GetImageGroup | public ImageGroup GetImageGroup(long groupImageId) |
Returns the single ImageGroup matching groupImageId via Session.Query<ImageGroup>().Single(), throwing if none exists. Applies neither the confidential nor the deleted-image visibility filter (SQL-023; see Security and authorization). |
| GetImageGroupOrDefault | public ImageGroup GetImageGroupOrDefault(long groupImageId) |
Same as GetImageGroup but returns null instead of throwing when no match exists (SQL-024; applies neither visibility filter — see Security and authorization). |
| GetFilteredImageGroups | public IEnumerable<ImageGroup> GetFilteredImageGroups(string groupId, ImageFilterCriteria filter) |
Returns ImageGroups for the given group/parent-group id, filtered by category, document type, create user, and date range (sentinel values mean "no filter", SDN-BR-041), then applies the deleted-image filter (ImageDeleteCode != null \|\| filter.CanUserSeeDeletedImages, inverted — see SC-SDN-01) and the confidential-image filter (SecurityLevel == NonConfidentialSecurityLevel \|\| filter.CanUserSeeConfidentialImages, SDN-BR-043) in memory after materializing the query with ToList() (SQL-025). |
Inherited public members¶
Members in this section are inherited from RepositoryBase<ImageGroup> in SAIF.Framework.Data.NHibernate. They are available on this type through inheritance.
| Member | Signature | Purpose | Origin |
|---|---|---|---|
| Add | public void Add(ImageGroup entity) |
Registers a new ImageGroup entity for insertion on the next unit-of-work commit.† |
SAIF.Framework.Data.NHibernate — RepositoryBase<ImageGroup> |
| Update | public void Update(ImageGroup entity) |
Marks an existing ImageGroup entity as modified for the next unit-of-work commit.† |
SAIF.Framework.Data.NHibernate — RepositoryBase<ImageGroup> |
| Delete(ImageGroup) | public void Delete(ImageGroup entity) |
Registers an ImageGroup entity for deletion on the next unit-of-work commit; distinct from this type's own Delete(ImageDelete) overload above, which performs a soft delete instead.† |
SAIF.Framework.Data.NHibernate — RepositoryBase<ImageGroup> |
| Query | public IQueryable<ImageGroup> Query() |
Returns a LINQ-queryable session projection over ImageGroup for building ad hoc filters.† |
SAIF.Framework.Data.NHibernate — RepositoryBase<ImageGroup> |
| Get | public ImageGroup Get(object id) |
Loads an ImageGroup by primary key, returning null if not found.† |
SAIF.Framework.Data.NHibernate — RepositoryBase<ImageGroup> |
| Load | public ImageGroup Load(object id) |
Loads an ImageGroup by primary key as a (possibly proxied) reference, throwing if not found.† |
SAIF.Framework.Data.NHibernate — RepositoryBase<ImageGroup> |
| SystemDate | public DateTime SystemDate { get; } |
Current system date/time as tracked by the underlying session/unit of work.† | SAIF.Framework.Data.NHibernate — RepositoryBase<ImageGroup> |
Behavioral notes¶
- SC-SDN-01 (High):
GetFilteredImageGroupskeeps an image whenImageDeleteCode != null || CanUserSeeDeletedImages. Elsewhere (GroupImageRepository.Delete,ImagingDataModelExtensions.IsDeleted), null/empty/" "means not deleted and"Y"means deleted — so this predicate is backwards: it returns soft-deleted images ("Y", non-null) to users withoutCanUserSeeDeletedImages, while hiding never-deleted images (nullcode).Services/SAIF.Services/Groups/Imaging/ImageService.GetImagesrelies on this filter and applies no compensating filter of its own; by contrast,Services/SAIF.Services/Agencies/Imaging/ImageService.csuses the correct!Image.IsDeleted() || CanUserSeeDeletedImagespattern. This is an authorization bypass for deleted group images (saif-data-nhibernate-security-analysis.mdSC-SDN-01). - SC-SDN-02 (Medium): Both the deleted and confidential filters in
GetFilteredImageGroupsrun in memory afterToList(), so every image in the group is loaded before filtering — a performance and exposure-surface concern. GetImageGroup,GetImageGroupOrDefault, andImageFoundapply neither the confidential nor the deleted filter; any caller exposing an image by id via these members must enforce visibility itself (DLA-SDN-01/02, Security and authorization).Deleteperforms a soft delete only and does not checkCanUserEditImages; enforcement of edit permission is expected in the caller (SC-SDN-06).
Constraints and usage notes¶
- Do not treat
GetFilteredImageGroups' current deleted-image behavior as correct access control until SC-SDN-01 is fixed or confirmed intentional; verify with the owning team before relying on it in a new caller. GetImageGroupthrows if no matchingImageGroupexists; useGetImageGroupOrDefaultorImageFoundfirst when existence is not guaranteed.
Note: Statements marked with
†are derived from dependency library documentation via the Legends CLI. Statements marked with*were inferred from code structure or contextual evidence. Statements marked with**could not be confirmed; treat as unknown until verified.
Related documentation¶
- Index
- Overview
- Architecture
- Dependencies
- Operations and processes
- Business rules
- Database tables
- SQL catalog
- Procedures
- Security and authorization
- API reference
Sources¶
Data/SAIF.Data.NHibernate/Repositories/Groups/GroupImageRepository.cs