Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions server/controllers/e2ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,29 @@ func HandleGetVerificationStatus(w http.ResponseWriter, r *http.Request) {

_ = json.NewEncoder(w).Encode(models.JSONResponse{Success: true, Data: resp})
}

func HandleResetKeys(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
uid, _ := r.Context().Value(middlewares.UserIDKey).(string)

var req models.ResetKeysReq
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(models.JSONResponse{Success: false, Error: "Invalid JSON request payload"})
return
}

svc := services.NewE2EEService()
if err := svc.ResetKeys(r.Context(), uid, req.Password); err != nil {
w.WriteHeader(http.StatusUnauthorized)
_ = json.NewEncoder(w).Encode(models.JSONResponse{Success: false, Error: err.Error()})
return
}

_ = json.NewEncoder(w).Encode(models.JSONResponse{
Success: true,
Data: map[string]interface{}{
"message": "All encryption keys wiped successfully. Please re-generate and upload a new prekey bundle.",
},
})
}
4 changes: 4 additions & 0 deletions server/models/e2ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ type VerificationStatusResp struct {
VerifiedUserID string `json:"verified_user_id"`
IsVerified bool `json:"is_verified"`
}

type ResetKeysReq struct {
Password string `json:"password"`
}
29 changes: 29 additions & 0 deletions server/repository/e2ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,32 @@ func (r *E2EERepository) InvalidateUserVerifications(ctx context.Context, uid st
_, err := config.DB.Exec(ctx, query, uid)
return err
}

func (r *E2EERepository) ResetUserKeys(ctx context.Context, uid string) error {
tx, err := config.DB.Begin(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx)

_, err = tx.Exec(ctx, `DELETE FROM user_devices WHERE user_id = $1::uuid;`, uid)
if err != nil {
return err
}

_, err = tx.Exec(ctx, `DELETE FROM one_time_prekeys WHERE user_id = $1::uuid;`, uid)
if err != nil {
return err
}

_, err = tx.Exec(ctx, `
UPDATE user_verifications
SET is_verified = FALSE, updated_at = NOW()
WHERE verified_user_id = $1::uuid;
`, uid)
if err != nil {
return err
}

return tx.Commit(ctx)
}
2 changes: 2 additions & 0 deletions server/routes/e2ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ func E2EERoute(router chi.Router) {

router.Post("/verify", controllers.HandleSetVerification)
router.Get("/verify/{userId}", controllers.HandleGetVerificationStatus)

router.Post("/reset", controllers.HandleResetKeys)
}
24 changes: 24 additions & 0 deletions server/services/e2ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"

"github.com/commandlinecoding/elephant/server/config"
"github.com/commandlinecoding/elephant/server/models"
"github.com/commandlinecoding/elephant/server/repository"
)
Expand Down Expand Up @@ -63,3 +64,26 @@ func (s *E2EEService) GetVerification(ctx context.Context, uid, targetUID string
IsVerified: isVerified,
}, nil
}

func (s *E2EEService) ResetKeys(ctx context.Context, uid string, password string) error {

var passwordHash string
query := `SELECT password_hash FROM users WHERE id = $1::uuid;`
err := config.DB.QueryRow(ctx, query, uid).Scan(&passwordHash)
if err != nil {
return errors.New("user account context not found")
}

if passwordHash != "" {
if password == "" {
return errors.New("password required for re-authentication")
}

match, err := VerifyPassword(password, passwordHash)
if err != nil || !match {
return errors.New("invalid password re-authentication attempt")
}
}

return s.repo.ResetUserKeys(ctx, uid)
}
Loading