Skip to content

Extract identity/account bounded context into Identity service - #91

Open
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1789050400-identity-extraction
Open

devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1789050400-identity-extraction

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Ports the identity/account bounded context out of quickapp-monolith into src/Services/Identity, keeping the route shape and token behavior identical so the Angular client works unchanged when pointed at the gateway. Everything lands behind the existing YARP route /api/identity/* (prefix stripped), so /api/identity/connect/token and /api/identity/api/account/* answer on :5000. src/ApiGateway/** is untouched.

Layout follows the boundaries doc:

  • Identity.DomainApplicationUser, ApplicationRole, ApplicationPermission, ApplicationPermissions, CustomClaims, account exceptions, service interfaces. No EF, no ASP.NET.
  • Identity.InfrastructureIdentityDbContext (ASP.NET Identity + OpenIddict tables, auditing via IUserIdAccessor), UserAccountService, UserRoleService, DatabaseSeeder, initial Npgsql migration.
  • Identity.APIAuthorizationController (~/connect/token, password + refresh_token), UserAccountController (api/account/users*), UserRoleController (api/account/roles*, api/account/permissions), OidcServerConfig, authorization policies/requirements/handlers, ViewModels/Account/*, AutoMapper profile.
  • Identity.Tests — xUnit, added to src/Microservices.sln.

Cross-context links cut

The two places the monolith reached into Order-owned data are gone; no other behavior was redesigned:

 public class ApplicationUser : IdentityUser
-    public ICollection<Order> Orders { get; set; }

 public async Task<(bool Success, string[] Errors)> TestCanDeleteUserAsync(string userId)
-    if (await _context.Orders.Where(o => o.CashierId == userId).AnyAsync())
-        errors.Add("User has associated orders");
+    // Orders are owned by the Order service; a user id is a scalar reference there.
+    return (true, []);

MappingProfile keeps only the account maps (the monolith's Customer/Product/Order maps are dropped), and DatabaseSeeder seeds only roles/users/OpenIddict clients — no shop demo data.

Seeded state (unchanged from the monolith)

administrator (all permission values) and user (none); accounts admin / user, both tempP@ss123; OpenIddict clients quickapp_spa and swagger_ui; custom claims fullname, jobtitle, configuration, permission, with the Identity security stamp excluded from tokens.

Notable deltas from a straight copy

  • DatabaseSeeder retries MigrateAsync() (10 × 5s) — compose has depends_on: postgres but no healthcheck, so a cold up otherwise races the database and the service exits.
  • Signing/encryption keys: an X.509 cert is used when OIDC:Certificates:Path is set, otherwise ephemeral keys (the monolith's dev-certificate store isn't usable in the container). Tokens do not survive a service restart in compose; production needs the cert config.
  • AutoMapper is 15.1.1, not the monolith's 13.0.1: 13.x/14.x are flagged by GHSA-rvv3-g6hj-g44x. This changes only the registration call (AddAutoMapper(cfg => cfg.AddMaps(...))).

Verification

$ dotnet build Services/Identity/Identity.API/Identity.API.csproj -c Release
Build succeeded.

$ dotnet test Services/Identity/Identity.Tests/Identity.Tests.csproj
Passed! - Failed: 0, Passed: 11, Skipped: 0, Total: 11

Through the gateway on :5000 (compose, postgres + identity-service + api-gateway):

$ curl -s -o /dev/null -w '%{http_code}\n' -X POST http://localhost:5000/api/identity/connect/token \
    -d 'grant_type=password&username=admin&password=tempP%40ss123&client_id=quickapp_spa&scope=openid email phone profile roles offline_access'
200
# -> {"access_token":"eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZDQkMtSFM1MTIi...","refresh_token":"...","expires_in":3599}

$ curl -s http://localhost:5000/api/identity/api/account/users/me -H "Authorization: Bearer $AT"
{"isLockedOut":false,"roles":["administrator"],"id":"378768e3-6fb0-479e-b17f-f31ba7a73d40","userName":"admin",
 "fullName":"Inbuilt Administrator","email":"admin@ebenmonney.com","phoneNumber":"+1 (123) 000-0000","isEnabled":true}

$ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:5000/api/identity/api/account/roles -H "Authorization: Bearer $AT"
200

$ curl -s -o /dev/null -w '%{http_code}\n' -X POST http://localhost:5000/api/identity/connect/token \
    -d "grant_type=refresh_token&client_id=quickapp_spa&refresh_token=$RT"
200

$ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:5000/api/identity/api/account/users/me
401

Blockers hit while verifying (not fixed here)

  • docker compose -f src/docker-compose.yml up --build does not complete: notification-service fails to build on the known pre-existing bug — Notification.API.csproj references ..\..\Shared instead of ..\..\..\Shared. Per the boundaries doc that file is not mine to touch, so the boot above was scoped to postgres, identity-service and api-gateway (--no-deps). Everything else in the compose file builds.
  • rabbitmq:3-management-alpine could not be pulled on this machine (Docker Hub 429 / mirror data cap). Identity does not use RabbitMQ, so it was skipped.

Expected conflicts with the Customer PR (#88)

Two overlaps, both trivial, to be resolved by rebasing onto main after #88 merges:

Leftover TODOs: persistent signing/encryption certificates for non-local environments; a compose healthcheck on postgres would let the seeder retry loop go away.

Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/edccab73d9404e79bc20b6d17042f787

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

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.

1 participant