Add delete account endpoint and file encryption at rest
Delete Account (Plan #2): - DELETE /api/auth/account/ with password or "DELETE" confirmation - Cascade delete across 15+ tables in correct FK order - Auth provider detection (email/apple/google) for /auth/me/ - File cleanup after account deletion - Handler + repository tests (12 tests) Encryption at Rest (Plan #3): - AES-256-GCM envelope encryption (per-file DEK wrapped by KEK) - Encrypt on upload, auto-decrypt on serve via StorageService.ReadFile() - MediaHandler serves decrypted files via c.Blob() - TaskService email image loading uses ReadFile() - cmd/migrate-encrypt CLI tool with --dry-run for existing files - Encryption service + storage service tests (18 tests)
This commit is contained in:
@@ -63,3 +63,9 @@ type AppleSignInRequest struct {
|
||||
type GoogleSignInRequest struct {
|
||||
IDToken string `json:"id_token" validate:"required"` // Google ID token from Credential Manager
|
||||
}
|
||||
|
||||
// DeleteAccountRequest represents the delete account request body
|
||||
type DeleteAccountRequest struct {
|
||||
Password *string `json:"password"`
|
||||
Confirmation *string `json:"confirmation"`
|
||||
}
|
||||
|
||||
@@ -45,15 +45,16 @@ type RegisterResponse struct {
|
||||
|
||||
// CurrentUserResponse represents the /auth/me/ response
|
||||
type CurrentUserResponse struct {
|
||||
ID uint `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
IsActive bool `json:"is_active"`
|
||||
DateJoined time.Time `json:"date_joined"`
|
||||
LastLogin *time.Time `json:"last_login,omitempty"`
|
||||
Profile *UserProfileResponse `json:"profile,omitempty"`
|
||||
ID uint `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
IsActive bool `json:"is_active"`
|
||||
DateJoined time.Time `json:"date_joined"`
|
||||
LastLogin *time.Time `json:"last_login,omitempty"`
|
||||
Profile *UserProfileResponse `json:"profile,omitempty"`
|
||||
AuthProvider string `json:"auth_provider"`
|
||||
}
|
||||
|
||||
// VerifyEmailResponse represents the email verification response
|
||||
@@ -125,17 +126,18 @@ func NewUserProfileResponse(profile *models.UserProfile) *UserProfileResponse {
|
||||
}
|
||||
|
||||
// NewCurrentUserResponse creates a CurrentUserResponse from a User model
|
||||
func NewCurrentUserResponse(user *models.User) CurrentUserResponse {
|
||||
func NewCurrentUserResponse(user *models.User, authProvider string) CurrentUserResponse {
|
||||
return CurrentUserResponse{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Email: user.Email,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
IsActive: user.IsActive,
|
||||
DateJoined: user.DateJoined,
|
||||
LastLogin: user.LastLogin,
|
||||
Profile: NewUserProfileResponse(user.Profile),
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Email: user.Email,
|
||||
FirstName: user.FirstName,
|
||||
LastName: user.LastName,
|
||||
IsActive: user.IsActive,
|
||||
DateJoined: user.DateJoined,
|
||||
LastLogin: user.LastLogin,
|
||||
Profile: NewUserProfileResponse(user.Profile),
|
||||
AuthProvider: authProvider,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user