Skip to content

ARCH-001 Phase 25: consolidate Admin/Store PictureController - #826

Merged
KrzysztofPajak merged 2 commits into
developfrom
arch001/phase25-picture-consolidation
Sep 11, 2026
Merged

ARCH-001 Phase 25: consolidate Admin/Store PictureController#826
KrzysztofPajak merged 2 commits into
developfrom
arch001/phase25-picture-consolidation

Conversation

@KrzysztofPajak

Copy link
Copy Markdown
Member

ARCH-001 Phase 25: PictureController consolidation

Fresh survey of remaining Admin/Store/Vendor duplication (requested by user) found
Admin's and Store's PictureController were byte-identical — only namespace
and base class differed. No domain entity, no per-store/per-vendor scope concept
at all, so unlike every other Base*Controller in this initiative, no
IAdminDataScope<TEntity> was needed. Vendor never had its own copy.

Change

Both AsyncUpload/AsyncLogoUpload actions moved verbatim into a new
BasePictureController in Grand.Web.AdminShared, carrying
[PermissionAuthorize(PermissionSystemName.Pictures)] and
[AutoValidateAntiforgeryToken]. Admin's and Store's PictureController are now
thin subclasses restating their host's [AuthorizeAdmin|AuthorizeStore]/[Area]/
[AuthorizeMenu] attribute set — same shape as BaseProductController,
BaseEmailAccountController, etc. No behavior change.

Tests

No prior test coverage existed for either controller. Added:

  • BasePictureControllerTests — upload/logo-upload success and failure branches
    (null file, missing objectId, disallowed file type, permission denial). Uses
    the repo's established reflection-based anonymous-JSON-property read pattern
    (GetType().GetProperty(...)), since the base controller's anonymous JSON
    payloads are internal to Grand.Web.AdminShared and unreachable via dynamic
    from the test assembly.
  • PictureControllerAttributeTests (Admin + Store) — subclass/attribute wiring,
    same shape as EmailAccountControllerAttributeTests.

Verification

dotnet build GrandNode.sln — 0 errors. Per-project test runs (parallel
full-solution runs are known-flaky, see repo history):

  • Grand.Web.Admin.Tests: 1439/1439
  • Grand.Web.Store.Tests: 141/141

No live smoke test run — this change carries no cross-tenant/access-control
surface (identical logic moved, permission attribute unchanged), same
justification as Phase 24 (Currency/Language cleanup).

…ePictureController

Admin's and Store's PictureController were byte-identical (only namespace and
base class differed) - no domain entity, no per-store/per-vendor scope, so no
IAdminDataScope is needed here, unlike every other Base*Controller in this
initiative. Vendor never had its own copy.

Both AsyncUpload/AsyncLogoUpload actions moved into a new BasePictureController
in Grand.Web.AdminShared, carrying [PermissionAuthorize(PermissionSystemName.Pictures)]
and [AutoValidateAntiforgeryToken]. Admin/Store PictureController are now thin
subclasses restating their host's [AuthorizeAdmin|Store]/[Area]/[AuthorizeMenu]
attribute set, matching the established ARCH-001 pattern (BaseProductController,
BaseEmailAccountController, etc.).

No prior test coverage existed for either controller. Added:
- BasePictureControllerTests: upload/logo-upload success and failure branches
  (null file, missing objectId, disallowed file type, permission denial),
  using the repo's reflection-based anonymous-JSON-property pattern since the
  base controller's payloads are internal to a different assembly than the test.
- PictureControllerAttributeTests (Admin + Store): subclass/attribute wiring,
  same shape as EmailAccountControllerAttributeTests.

No behavior change. Verified: dotnet build GrandNode.sln 0 errors; Admin
1439/1439, Store 141/141 (run separately, per known parallel-run flakiness).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013y3MqvZq7y1Uc5p4JZad2i
Copilot AI lite review requested due to automatic review settings September 11, 2026 01:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KrzysztofPajak

This comment was marked as off-topic.

Comment thread src/Web/Grand.Web.AdminShared/Controllers/BasePictureController.cs Dismissed
github-code-quality flagged a local MemoryStream created in
AsyncUpload_AllowedFileType_InsertsPictureAndReturnsSuccessJson without a
Dispose call. Wrapped in a using declaration.

The other flagged finding (generic catch(Exception) in AsyncLogoUpload) is
preserved pre-existing behavior, byte-for-byte identical in both original
Admin and Store controllers before this PR - not introduced by this
consolidation, left as-is per this initiative's no-behavior-change scope,
replied on the review thread accordingly.

Verified: Grand.Web.Admin.Tests Picture-filtered run 50/50 green.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013y3MqvZq7y1Uc5p4JZad2i
@KrzysztofPajak

Copy link
Copy Markdown
Member Author

Both automated findings addressed:

  1. Missing Dispose on MemoryStream (BasePictureControllerTests.cs:112) — fixed in bdddb4e, wrapped in a using declaration.
  2. Generic catch clause (BasePictureController.cs:126) — verified this is preserved pre-existing behavior: both the original Admin and Store PictureControllers had the identical catch (Exception ex) at this spot before this PR (git show develop:.../PictureController.cs). Narrowing it would be a real behavior change (currently any file-write failure returns a graceful JSON error; narrowing to e.g. IOException would let other exceptions surface as 500s instead) — out of scope for a pure consolidation move with a no-behavior-change goal. Left as-is; flagging for a future dedicated cleanup pass if the maintainers want it narrowed.

@KrzysztofPajak
KrzysztofPajak merged commit a1c414e into develop Sep 11, 2026
6 checks passed
@KrzysztofPajak
KrzysztofPajak deleted the arch001/phase25-picture-consolidation branch September 11, 2026 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants