first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:37:58 +03:00
commit 8b1fbdee99
104 changed files with 23398 additions and 0 deletions

414
SOFT_DELETE_MANAGEMENT.md Normal file
View File

@@ -0,0 +1,414 @@
# Soft Delete Kullanıcı Yönetimi
## Genel Bakış
AuthCentral'da silinen kullanıcılar soft delete ile yönetilir. Bu, kullanıcıların veritabanından silinmeden sadece işaretlenerek pasif hale getirilmesi anlamına gelir.
## Yeni Endpoint'ler
### 1. Silinen Kullanıcıları Listele
```bash
GET /v1/admin/users/deleted
```
**Query Parameters:**
- `page` (int, optional) - Sayfa numarası (default: 1)
- `limit` (int, optional) - Sayfa başına kayıt (default: 10, max: 100)
**Örnek:**
```bash
TOKEN=$(curl -s -X POST http://localhost:8080/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@gauth.local","password":"Admin@123"}' | jq -r '.access_token')
curl -X GET "http://localhost:8080/v1/admin/users/deleted?page=1&limit=10" \
-H "Authorization: Bearer $TOKEN"
```
**Yanıt:**
```json
{
"users": [
{
"id": "ca567947-ef2a-49ad-b955-bf0ef6bbf136",
"username": "Delete Me",
"email": "deleteme@test.com",
"avatar": "",
"email_verified": true,
"created_at": "2026-02-05T00:03:08.360433+03:00",
"updated_at": "2026-02-05T00:03:08.38027+03:00",
"deleted_at": "2026-02-05T00:03:25.549299+03:00",
"roles": [
{
"id": 2,
"name": "user",
"description": "Default user role"
}
],
"social_accounts": []
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 12,
"totalPages": 2
}
}
```
**Özellikler:**
-`deleted_at` field'ı görünür (normal endpoint'lerde gizli)
- ✅ Pagination desteği
- ✅ Sadece soft delete edilmiş kullanıcılar gösterilir
- ✅ En son silinen kullanıcılar önce gelir (deleted_at DESC)
### 2. Kullanıcıyı Geri Yükle (Restore)
```bash
POST /v1/admin/users/{id}/restore
```
**Path Parameters:**
- `id` (uuid, required) - Kullanıcı ID
**Örnek:**
```bash
TOKEN=$(curl -s -X POST http://localhost:8080/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@gauth.local","password":"Admin@123"}' | jq -r '.access_token')
USER_ID="ca567947-ef2a-49ad-b955-bf0ef6bbf136"
curl -X POST "http://localhost:8080/v1/admin/users/$USER_ID/restore" \
-H "Authorization: Bearer $TOKEN"
```
**Başarılı Yanıt:**
```json
{
"message": "User restored successfully"
}
```
**Hata Yanıtları:**
```json
{
"error": "deleted user not found"
}
```
## Kullanım Senaryoları
### Senaryo 1: Silinen Kullanıcıları İnceleme
```bash
#!/bin/bash
# Admin login
TOKEN=$(curl -s -X POST http://localhost:8080/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@gauth.local","password":"Admin@123"}' | jq -r '.access_token')
# Tüm silinen kullanıcıları listele
echo "=== Deleted Users ==="
curl -s -X GET "http://localhost:8080/v1/admin/users/deleted" \
-H "Authorization: Bearer $TOKEN" | jq '.users[] | {id, email, username, deleted_at}'
```
### Senaryo 2: Kullanıcıyı Soft Delete ve Restore
```bash
#!/bin/bash
TOKEN=$(curl -s -X POST http://localhost:8080/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@gauth.local","password":"Admin@123"}' | jq -r '.access_token')
USER_ID="abc-123-def-456"
# 1. Kullanıcıyı soft delete yap
echo "Step 1: Soft delete user"
curl -s -X DELETE "http://localhost:8080/v1/admin/users/$USER_ID" \
-H "Authorization: Bearer $TOKEN" | jq '.'
# 2. Silinen kullanıcılar listesinde kontrol et
echo -e "\nStep 2: Check deleted users"
curl -s -X GET "http://localhost:8080/v1/admin/users/deleted" \
-H "Authorization: Bearer $TOKEN" | jq ".users[] | select(.id==\"$USER_ID\")"
# 3. Kullanıcıyı geri yükle
echo -e "\nStep 3: Restore user"
curl -s -X POST "http://localhost:8080/v1/admin/users/$USER_ID/restore" \
-H "Authorization: Bearer $TOKEN" | jq '.'
# 4. Normal kullanıcı listesinde kontrol et
echo -e "\nStep 4: Verify user is restored"
curl -s -X GET "http://localhost:8080/v1/admin/users/$USER_ID" \
-H "Authorization: Bearer $TOKEN" | jq '{id, email, username}'
```
### Senaryo 3: Frontend İçin Silinen Kullanıcılar Yönetimi
**Frontend JavaScript Örneği:**
```javascript
// API Client
class AdminAPI {
constructor(baseURL, token) {
this.baseURL = baseURL;
this.token = token;
}
async getDeletedUsers(page = 1, limit = 10) {
const response = await fetch(
`${this.baseURL}/v1/admin/users/deleted?page=${page}&limit=${limit}`,
{
headers: {
'Authorization': `Bearer ${this.token}`
}
}
);
return response.json();
}
async restoreUser(userId) {
const response = await fetch(
`${this.baseURL}/v1/admin/users/${userId}/restore`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${this.token}`
}
}
);
return response.json();
}
async softDeleteUser(userId) {
const response = await fetch(
`${this.baseURL}/v1/admin/users/${userId}`,
{
method: 'DELETE',
headers: {
'Authorization': `Bearer ${this.token}`
}
}
);
return response.json();
}
async hardDeleteUser(userId) {
const response = await fetch(
`${this.baseURL}/v1/admin/users/${userId}?hard=true`,
{
method: 'DELETE',
headers: {
'Authorization': `Bearer ${this.token}`
}
}
);
return response.json();
}
}
// Kullanım
const admin = new AdminAPI('http://localhost:8080', YOUR_TOKEN);
// Silinen kullanıcıları getir
const deletedUsers = await admin.getDeletedUsers(1, 10);
console.log(deletedUsers);
// Kullanıcıyı geri yükle
const result = await admin.restoreUser('user-uuid-here');
console.log(result);
```
## API Endpoint'leri Özeti
| Endpoint | Method | Açıklama | Query/Body |
|----------|--------|----------|------------|
| `/v1/admin/users` | GET | Aktif kullanıcılar | `?page=1&limit=10` |
| `/v1/admin/users/deleted` | GET | **Silinen kullanıcılar** | `?page=1&limit=10` |
| `/v1/admin/users/{id}` | DELETE | Soft delete | - |
| `/v1/admin/users/{id}?hard=true` | DELETE | Hard delete (kalıcı) | `?hard=true` |
| `/v1/admin/users/{id}/restore` | POST | **Kullanıcıyı geri yükle** | - |
## Soft Delete vs Hard Delete
| Özellik | Soft Delete | Hard Delete |
|---------|-------------|-------------|
| **Veritabanı** | `deleted_at` timestamp set edilir | Tamamen silinir |
| **Görünürlük** | `/deleted` endpoint'inde görünür | Hiçbir yerde görünmez |
| **Geri Getirme** | ✅ `/restore` ile mümkün | ❌ İmkansız |
| **İlişkiler** | Korunur | Silinir |
| **Kullanım** | Varsayılan, güvenli | Dikkatli kullanılmalı |
| **Komut** | `DELETE /users/{id}` | `DELETE /users/{id}?hard=true` |
## Frontend Entegrasyonu
### React Örneği
```jsx
import React, { useState, useEffect } from 'react';
function DeletedUsersManager() {
const [deletedUsers, setDeletedUsers] = useState([]);
const [loading, setLoading] = useState(false);
const [page, setPage] = useState(1);
const fetchDeletedUsers = async () => {
setLoading(true);
try {
const response = await fetch(
`http://localhost:8080/v1/admin/users/deleted?page=${page}&limit=10`,
{
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
}
);
const data = await response.json();
setDeletedUsers(data.users);
} catch (error) {
console.error('Error fetching deleted users:', error);
} finally {
setLoading(false);
}
};
const restoreUser = async (userId) => {
if (!confirm('Bu kullanıcıyı geri yüklemek istediğinize emin misiniz?')) {
return;
}
try {
const response = await fetch(
`http://localhost:8080/v1/admin/users/${userId}/restore`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
}
);
if (response.ok) {
alert('Kullanıcı başarıyla geri yüklendi!');
fetchDeletedUsers(); // Listeyi yenile
}
} catch (error) {
console.error('Error restoring user:', error);
}
};
useEffect(() => {
fetchDeletedUsers();
}, [page]);
return (
<div className="deleted-users-manager">
<h2>Silinen Kullanıcılar</h2>
{loading ? (
<p>Yükleniyor...</p>
) : (
<table>
<thead>
<tr>
<th>Email</th>
<th>Kullanıcı Adı</th>
<th>Silinme Tarihi</th>
<th>İşlemler</th>
</tr>
</thead>
<tbody>
{deletedUsers.map(user => (
<tr key={user.id}>
<td>{user.email}</td>
<td>{user.username}</td>
<td>{new Date(user.deleted_at).toLocaleString('tr-TR')}</td>
<td>
<button onClick={() => restoreUser(user.id)}>
Geri Yükle
</button>
</td>
</tr>
))}
</tbody>
</table>
)}
<div className="pagination">
<button onClick={() => setPage(p => Math.max(1, p - 1))}>
Önceki
</button>
<span>Sayfa {page}</span>
<button onClick={() => setPage(p => p + 1)}>
Sonraki
</button>
</div>
</div>
);
}
export default DeletedUsersManager;
```
## Güvenlik Notları
**İyi Pratikler:**
- Silinen kullanıcıları düzenli olarak gözden geçirin
- Restore işleminden önce kullanıcıyı doğrulayın
- Hard delete yapmadan önce soft delete kullanın
- Kritik kullanıcılar için restore geçmişi tutun
⚠️ **Dikkat Edilmesi Gerekenler:**
- Sadece admin rolündeki kullanıcılar bu endpoint'lere erişebilir
- Restore edilen kullanıcı önceki tüm rolleri ve ayarları ile geri gelir
- Soft delete edilmiş kullanıcılar login yapamaz
- Hard delete geri alınamaz, dikkatli kullanın
## Test Komutları
```bash
# 1. Kullanıcı oluştur
TOKEN=$(curl -s -X POST http://localhost:8080/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@gauth.local","password":"Admin@123"}' | jq -r '.access_token')
curl -X POST http://localhost:8080/v1/admin/users \
-H "Authorization: Bearer $TOKEN" \
-F "email=test@example.com" \
-F "password=test123" \
-F "user_name=Test User" \
-F "roles=user"
# 2. Kullanıcıyı soft delete yap
curl -X DELETE "http://localhost:8080/v1/admin/users/USER_ID" \
-H "Authorization: Bearer $TOKEN"
# 3. Silinen kullanıcıları listele
curl -X GET "http://localhost:8080/v1/admin/users/deleted" \
-H "Authorization: Bearer $TOKEN" | jq '.'
# 4. Kullanıcıyı geri yükle
curl -X POST "http://localhost:8080/v1/admin/users/USER_ID/restore" \
-H "Authorization: Bearer $TOKEN"
```
## Özet
🎯 **Yeni Özellikler:**
- ✅ Silinen kullanıcıları listeleme
- ✅ Kullanıcıyı geri yükleme (restore)
-`deleted_at` field'ı görünürlüğü
- ✅ Pagination desteği
- ✅ Frontend entegrasyonu için hazır
📊 **Kullanım:**
- Soft delete varsayılan silme yöntemi
- Hard delete sadece kalıcı silme için
- Restore ile yanlışlıkla silinen kullanıcılar kurtarılabilir
- Frontend'de silinen kullanıcılar yönetilebilir