Skip to content

Feat/add otp verification#29

Closed
Rashed99Azm wants to merge 23 commits into
mainfrom
feat/add-otp-verification
Closed

Feat/add otp verification#29
Rashed99Azm wants to merge 23 commits into
mainfrom
feat/add-otp-verification

Conversation

@Rashed99Azm
Copy link
Copy Markdown
Collaborator

Summary
Adds a complete OTP verification system with request/verify endpoints, domain entities, application layer, infrastructure, and database migration.
Changes
Domain

  • OtpVerification aggregate root with 5-minute expiry, 60s resend cooldown, 5-attempt limit, and hash-based code storage
  • UserVerification entity tracking verified contacts per user
  • OtpVerificationType enum (Sms / Email)
    Application
  • RequestVerificationCommand + handler: generates OTP, stores hash, dispatches via INotificationGateway (OTP_VERIFICATION template)
  • VerifyOtpCommand + handler: validates code with early-exit checks (not found, expired, invalidated, max attempts), stamps EmailConfirmed/PhoneNumberConfirmed on matching user
  • IUserRepository with FindUserIdByContactAsync and StampConfirmedAsync
  • Validators for both commands
  • DTOs: RequestVerificationResponseDto, VerifyOtpResponseDto
  • System codes ERR120–ERR125, CON060–CON061 with bilingual messages
  • Refactored VerifyOtpCommandHandler to use repository pattern instead of direct ICceDbContext queries
    Infrastructure
  • EF Core configurations for otp_verifications and user_verifications tables
  • OtpVerificationRepository, UserVerificationRepository, UserRepository implementations
  • OtpCodeGenerator using HMACSHA256 with configurable secret
  • DI registration for all verification services
  • AddOtpVerification migration
    API (External)
  • POST /verification/request — request an OTP (anonymous)
  • POST /verification/verify — verify code (anonymous)
  • Otp:HmacSecret added to appsettings (dev + base)
    Seeder
  • OTP_VERIFICATION notification template seeded for Email and SMS channels
    Bug Fixes
  • Fixed DbUpdateConcurrencyException on user confirm: User.ConcurrencyStamp (ASP.NET Identity concurrency token) was null on the stub, causing EF's UPDATE WHERE clause to match 0 rows. Now loads the current stamp before attaching.
  • Restored pre-existing missing sub-namespace usings in DependencyInjection.cs
  • Fixed missing using CCE.Application.Notifications.Messages in MessagingOptions.cs (CS1574)

rashed99mm and others added 23 commits May 14, 2026 16:56
- Fix CA1859/CA2263 analyzer errors in Domain and Application tests
- Suppress CA1873 false positives in Directory.Build.props with justification
- Add JWT Bearer security definition to Swagger (Authorize button)
- Catch RedisException in output-cache middleware to allow startup without Redis
- Apply EF migrations to remote dev SQL Server
- Seed demo data (categories, news, events, posts, roles)
Bumps all project TFMs from net8.0 to net10.0 and updates
package references to compatible versions.
- Directory.Build.props: <TargetFramework>net10.0</TargetFramework>
- Roslyn source generator remains on netstandard2.0
- All test projects updated to net10.0
- Adds ApplicationErrors with typed error codes (Identity.PASSWORD_RESET,
  EMAIL_EXISTS, INVALID_CREDENTIALS, etc.)
- Introduces Result<T> monad for command/query return types
- Adds localization service with YAML-backed stores
- Integrates ValidationBehavior and ResultValidationBehavior
  into MediatR pipeline
- DomainException / ConcurrencyException / DuplicateException
  mapped to problem details via middleware
Replaces coarse-grained domain services (ICommunityWriteService,
ICountryProfileService, etc.) with aggregate-specific repository
interfaces aligned to DDD per-aggregate persistence.
- Introduces I*Repository interfaces per aggregate root
- Updates command/query handlers to depend on repositories
- Infrastructure layer implements repository interfaces with EF Core
- Removes obsolete service abstractions from Application layer
- Added AuditableAggregateRoot for creation and update tracking
- Added SoftDeleteAggregateRoot for logical deletion support

- Improved domain consistency across aggregates
…y, unify repository commit pattern

-
IAuthService (Login, RefreshToken, Logout, Register, ForgotPassword, ResetPassword): all 6 auth handlers reduced to thin wrappers (2 deps each instead of 4–6); duplicated token rotation/issuance logic eliminated; wrong ResetPassword domain keys fixed (INVALID_REFRESH_TOKEN → INVALID_RESET_TOKEN, REGISTRATION_FAILED → RESET_FAILED)
-
Refresh token repos no longer own commits: SaveChangesAsync removed from IRefreshTokenRepository / RefreshTokenRepository — AuthService owns commit via ICceDbContext
-
DDD hierarchy aligned: Entity<TId> constrained to IEquatable<TId>, domain events moved to AggregateRoot<TId> (inherits SoftDeletableEntity), deleted AuditableAggregateRoot/SoftDeletableAggregateRoot, upgraded 3 entities to AggregateRoot, updated 12 entity base classes
-
Generic repository pattern: IRepository<T,TId> + Repository<T,TId> base for aggregate repos
-
Handler commit ownership: IStateRepAssignmentRepository, IExpertRequestSubmissionRepository, IExpertWorkflowRepository, IUserProfileRepository — all SaveChangesAsync calls moved to handl
BREAKING CHANGE: Response.message is now a plain string instead of
{ ar, en } bilingual object, and FieldError.message is also a string.
LocalizationService.GetString() now defaults to
CultureInfo.CurrentUICulture (set by LocalizationMiddleware from
the Accept-Language header) instead of hardcoded "ar".
Changes:
- Response<T>.Message: LocalizedMessage → string
- FieldError.Message: LocalizedMessage → string
- MessageFactory uses _l.GetString() instead of GetLocalizedMessage()
- ExceptionHandlingMiddleware returns single message string
- ResponseValidationBehavior uses GetString() for validation errors
-manage user status
- Optimize ListUsersQuery: single-projection with inline role sub-select, replace join-based role filter with EXISTS subquery
- Optimize GetUserByIdQuery: collapse two DB round-trips into one Select projection, replace ToList+SingleOrDefault with FirstOrDefaultAsync
- Fix auth token handling in user management flow
…ables

- Replace bilingual video_url with single field on HomepageSettings
- Extract KnowledgePartner as separate aggregate from AboutSettings
- Extract PolicySection with PolicySectionType enum from PoliciesSettings
- Promote GlossaryEntry, HomepageCountry to AggregateRoot<Guid>
- Add order_index to HomepageCountry and all collection tables
- Switch all handlers to Response<T> + MessageFactory pattern
- Add ICceDbContext.Add/Delete/DeleteRange generic write methods
- Add 12 new admin + public endpoints for CRUD (glossary, partners, sections)
- Register new repos, EF configs, DI, SystemCode mappings, Resources.yaml keys
- Regenerate AddPlatformSettings migration with updated schema (7 tables)
- Add MediaFile entity, EF config, repository, upload options
- Add UploadMedia, UpdateMediaMetadata, DeleteMedia, GetMediaById commands/queries
- Add MediaFileBriefDto for consistent POST/PUT/DELETE response shape
- Add Internal (port 5002) and External (port 5001) REST endpoints
- Add MEDIA_UPLOADED/UPDATED/DELETED localized success messages (AR/EN)
- Add ERR110-ERR113 error codes for file validation
- Create and apply EF migration AddMediaService
- Build 0 errors, 773 tests pass (4 pre-existing failures)
- Add Serilog.Sinks.Seq to ship structured logs to Seq
- Add OpenTelemetry with ASP.NET Core + HttpClient instrumentation
- Export traces to Seq via OTLP (http://localhost:5341/ingest/otlp)
- Enrich Serilog logs with TraceId/SpanId from Activity.Current
- Register AddCceOpenTelemetry in both External and Internal APIs
- Add Seq configuration section to appsettings.json (empty in prod, localhost in dev)
- Keep existing Prometheus metrics untouched
- Add `BypassSettings` flag to `NotificationDispatchRequest` so security
  notifications (password reset) always send regardless of user opt-out
- Replace `IPasswordResetEmailSender` with `INotificationGateway` in
  `AuthService.ForgotPasswordAsync` — sends through the notification system
- Add `NotificationChannel.Sms` to password reset dispatch alongside Email
- Add `PASSWORD_RESET` SMS template to `ReferenceDataSeeder` (short Arabic
  and English bodies suitable for SMS character limits)
- Fix seeder idempotency check in `SeedNotificationTemplatesAsync` to query
  by `(code, channel)` instead of deterministic ID, preventing duplicate-key
  errors on re-seed
- Delete unused `IPasswordResetEmailSender` interface and
  `PasswordResetEmailSender` implementation
…ices

Feat/add system notificaton services
- Domain: add OtpVerification aggregate, UserVerification entity, OtpVerificationType enum
- Application: add RequestVerification and VerifyOtp commands, handlers, validators, DTOs
- Application: add IOtpVerificationRepository, IUserVerificationRepository, IUserRepository, IOtpCodeGenerator
- Application: add OTP system codes (ERR120–ERR125, CON060–CON061) and message factory shortcuts
- Infrastructure: add EF configurations, repository implementations, HMAC-based OtpCodeGenerator
- Infrastructure: register verification services and UserRepository in DI
- API: add POST /verification/request and POST /verification/verify endpoints (anonymous)
- Seeder: add OTP_VERIFICATION notification template for Email and SMS channels
…rmation

- Domain: add OtpVerification aggregate, UserVerification entity, OtpVerificationType enum
- Application: add RequestVerification and VerifyOtp commands/handlers/validators/DTOs
- Application: add IUserRepository, IOtpVerificationRepository, IUserVerificationRepository, IOtpCodeGenerator
- Application: add OTP system codes (ERR120–ERR125, CON060–CON061) and message factory shortcuts
- Application: refactor VerifyOtpCommandHandler to use repositories instead of direct ICceDbContext queries
- Infrastructure: add EF configurations, repository implementations, HMAC-based OtpCodeGenerator
- Infrastructure: add UserRepository with FindUserIdByContactAsync and StampConfirmedAsync
- Infrastructure: fix ConcurrencyStamp null stub causing DbUpdateConcurrencyException on user confirm
- Infrastructure: restore pre-existing missing sub-namespace usings in DependencyInjection.cs
- Infrastructure: fix missing using in MessagingOptions.xml doc cref
- API: add POST /verification/request and POST /verification/verify endpoints (anonymous)
- API: add Otp:HmacSecret to appsettings (dev + base configs)
- Seeder: add OTP_VERIFICATION notification template
- Migration: AddOtpVerification
Copy link
Copy Markdown

@github-advanced-security github-advanced-security AI left a comment

Choose a reason for hiding this comment

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

Semgrep OSS found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

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.

3 participants