feat: change email, export my data, delete account (with data anonymization)
This commit is contained in:
1 parent
bb191c389a
commit
10a66cd979
123 files changed
+10789
-76
No files matched your search
@@ -242,6 +242,80 @@ func (u *UserRepository) UpdateDisplayName(userId uint32, displayName string) (d
|
||||
return mappers.UserToDomain(localUser), nil
|
||||
}
|
||||
|
||||
func (u *UserRepository) IsEmailInUse(email string, exceptUserId uint32) (bool, error) {
|
||||
return isEmailInUse(u.db, email, exceptUserId)
|
||||
}
|
||||
|
||||
func isEmailInUse(db *gorm.DB, email string, exceptUserId uint32) (bool, error) {
|
||||
var holders int64
|
||||
err := db.Model(&entity.User{}).Where("LOWER(email) = LOWER(?) AND id <> ?", email, exceptUserId).Count(&holders).Error
|
||||
return holders > 0, err
|
||||
}
|
||||
|
||||
func (u *UserRepository) SetPendingEmailChange(userId uint32, pendingEmail string, code string, expiration time.Time) (domainUser.User, error) {
|
||||
return u.updatePendingEmailChange(userId, map[string]any{
|
||||
"pending_email": mappers.DomainToNullableString(pendingEmail),
|
||||
"email_change_code": mappers.DomainToNullableString(code),
|
||||
"email_change_expiration": expiration,
|
||||
})
|
||||
}
|
||||
|
||||
func (u *UserRepository) ClearPendingEmailChange(userId uint32) (domainUser.User, error) {
|
||||
return u.updatePendingEmailChange(userId, clearedEmailChange())
|
||||
}
|
||||
|
||||
func clearedEmailChange() map[string]any {
|
||||
return map[string]any{
|
||||
"pending_email": nil,
|
||||
"email_change_code": nil,
|
||||
"email_change_expiration": time.Time{},
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserRepository) updatePendingEmailChange(userId uint32, columns map[string]any) (domainUser.User, error) {
|
||||
result := u.db.Model(&entity.User{}).Where("id = ?", userId).Updates(columns)
|
||||
if result.Error != nil {
|
||||
return domainUser.User{}, result.Error
|
||||
}
|
||||
return u.Get(userId)
|
||||
}
|
||||
|
||||
func (u *UserRepository) ConfirmEmailChange(userId uint32, pendingEmail string, code string, now time.Time) (domainUser.User, error) {
|
||||
taken, err := isEmailInUse(u.db, pendingEmail, userId)
|
||||
if err != nil {
|
||||
return domainUser.User{}, err
|
||||
}
|
||||
columns := clearedEmailChange()
|
||||
if !taken {
|
||||
columns["email"] = pendingEmail
|
||||
}
|
||||
result := pendingChangeOf(u.db, userId, pendingEmail, code).Where("email_change_expiration > ?", now).Updates(columns)
|
||||
if result.Error != nil && isUniqueViolation(result.Error) {
|
||||
return domainUser.User{}, u.refuseTakenAddress(userId, pendingEmail, code)
|
||||
}
|
||||
if result.Error != nil {
|
||||
return domainUser.User{}, result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return domainUser.User{}, domainUser.ErrInvalidEmailChangeCode
|
||||
}
|
||||
if taken {
|
||||
return domainUser.User{}, domainUser.ErrEmailUnavailable
|
||||
}
|
||||
return u.Get(userId)
|
||||
}
|
||||
|
||||
func (u *UserRepository) refuseTakenAddress(userId uint32, pendingEmail string, code string) error {
|
||||
if err := pendingChangeOf(u.db, userId, pendingEmail, code).Updates(clearedEmailChange()).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return domainUser.ErrEmailUnavailable
|
||||
}
|
||||
|
||||
func pendingChangeOf(db *gorm.DB, userId uint32, pendingEmail string, code string) *gorm.DB {
|
||||
return db.Model(&entity.User{}).Where("id = ? AND pending_email = ? AND email_change_code = ?", userId, pendingEmail, code)
|
||||
}
|
||||
|
||||
func (u *UserRepository) UpdateRole(id uint32, from uint32, to uint32, assignedBy uint32) (domainUser.User, error) {
|
||||
err := u.db.Transaction(func(tx *gorm.DB) error {
|
||||
query := tx.Model(&entity.User{}).Where("id = ? AND EXISTS (SELECT 1 FROM roles WHERE id = ?)", id, to)
|
||||
|
||||
Reference in new issue
Block a user