Skip to main content
Vatandaş kaydı, telefon numarasıyla OTP tabanlı bir self-registration akışıdır. Kayıt isteği bir User aggregate’ı Draft durumunda oluşturur, bir OTP üretir ve SMS ile gönderir; kullanıcı kodu doğrulayınca telefon “verified” işaretlenir. Bu akış tamamen lokal (User aggregate) çalışır — Keycloak’a gerek yoktur.
İlgili dosyalar: src/DiyanetCleanArchitecture.API/Controllers/AuthController.cs · Application/Features/Authentication/Website/Commands/SignUpUser/* · Domain/Services/UserRegistrationService.cs · Domain/AggregatesModel/UserAggregate/User.cs · Application/DomainEventHandlers/UserOtpGenerated/SendOtpSmsDomainEventHandler.cs

Sequence — kayıt (sign-up)

Adım adım

1

Controller — ince giriş noktası

AuthController.SignUp yalnızca komutu MediatR’a iletir. Başarıda 201 Created döner.
Command şekli (SignUpUserCommand): Phone (zorunlu), FullName?, Consents?. Validator Phone için MustBeValidMobilePhone(), FullName için boş olamaz + max 100 karakter kuralını uygular.
2

Domain service — uniqueness + factory

Handler önce UserRegistrationService.RegisterNewUserAsync çağırır. Bu servis telefon/e-posta global benzersizliğini spec ile kontrol eder ve geçerse new User(...) döner:
“Doğrulanmamış ama var olan” telefon ayrı mesajla ele alınır: kullanıcı kayıt yerine giriş akışına yönlendirilir. DomainException global exception handler tarafından 400’e çevrilir.
3

Aggregate — Draft kullanıcı + OTP challenge

User’ın internal ctor’u durumu Draft yapar ve UserCreatedDomainEvent biriktirir. Handler ardından OTP üretip aggregate’e ekler:
User.AddOtpChallenge içeride bir UserOtpChallenge (SMS için 1 dk geçerli) oluşturur ve UserOtpGeneratedDomainEvent biriktirir:
CanRequestOtp, Draft veya Active durumlar için true’dur — yeni kayıt Draft olduğundan geçer.
4

Kaydet — event dispatch + SMS

SaveEntitiesAsync, SaveChanges’ten sonra biriken domain event’leri dispatch eder. UserOtpGeneratedDomainEvent’i SendOtpSmsDomainEventHandler dinler:
IOtpSmsService implementasyonu (OtpSmsService) NetGSM OTP endpoint’ine Phone.ToNetGsmFormat() ile gönderir. Bkz. SMS Servisi.
5

Challenge token üret + dön

Handler aktif challenge’ı bulur ve sonraki adımda kullanılacak kısa ömürlü challenge token’ı üretir:
ChallengeToken, OTPChallenge JWT şemasıyla imzalanır ve userId + challengeId’yi taşır. SPA bunu saklar; SMS kodu girilince verify-otp çağrısında Authorization header’ında gönderir.
6

Aktivasyon — VerifyOtp

Kullanıcı SMS kodunu girer. SPA, challenge token’ı bearer olarak taşıyan verify-otp çağrısı yapar:
VerifyOtpCommandHandler, userId/challengeId’yi IOtpChallengeContext üzerinden (challenge token’dan) okur, kodu doğrular, telefonu “verified” işaretler ve oturum başlatır:
User.VerifyChallenge başarılıysa IsPhoneNumberVerified = true yapar ve UserPhoneNumberVerifiedDomainEvent yayar. Doğrulama detayları için OTP / TOTP Akışı.

Hata senaryoları

OTP kodu DB’de UserOtpChallenge.Code (bir OtpCode value object) olarak tutulur ve SMS sadece bir kez gönderilir. Kullanıcıya kod ulaşmazsa yeni kayıt değil, resend-otp çağrılmalıdır (cooldown 60 sn, maksimum 3 yeniden gönderim — bkz. OTP playbook’u).

İlgili

OTP / TOTP Akışı

VerifyOtp, ResendOtp ve TOTP detayları.

SMS Servisi

NetGSM entegrasyonu, test numaraları, encoding.

User Aggregate

Durumlar, çocuk entity’ler, metodlar.

Domain Event'ler

AddDomainEvent → dispatch mekaniği.