# 🎉 User Create & Update - Avatar Upload Desteği

## ✨ Yeni Özellik

Artık yeni kullanıcı oluştururken ve mevcut kullanıcıyı güncellerken **aynı request'te avatar da yükleyebilirsiniz!**

---

## 📋 Güncellenen Endpoint'ler

### 1. POST /v1/admin/users (Create User)

**Artık Multipart/Form-Data Destekliyor!**

**Önceden:**
```bash
# Sadece JSON
curl -X POST http://localhost:8080/v1/admin/users \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"Pass123!","user_name":"john"}'
```

**Şimdi:**
```bash
# Multipart ile avatar da ekleyebilirsiniz!
curl -X POST http://localhost:8080/v1/admin/users \
  -H "Authorization: Bearer ADMIN_TOKEN" \
  -F "email=user@example.com" \
  -F "password=Pass123!" \
  -F "user_name=john" \
  -F "email_verified=true" \
  -F "roles=admin,user" \
  -F "avatar=@/path/to/photo.jpg"
```

**Response:**
```json
{
  "id": "new-user-uuid",
  "username": "john",
  "email": "user@example.com",
  "avatar": "/uploads/avatars/new-user-uuid_1707012345.jpg",
  "email_verified": true,
  "roles": [
    {"name": "admin"},
    {"name": "user"}
  ],
  "created_at": "2026-02-04T..."
}
```

---

### 2. PUT /v1/admin/users/:id (Update User)

**Hem JSON hem Multipart Destekliyor!**

**JSON ile (avatar URL):**
```bash
curl -X PUT http://localhost:8080/v1/admin/users/USER_ID \
  -H "Authorization: Bearer ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "new@example.com",
    "user_name": "newname",
    "roles": ["admin"]
  }'
```

**Multipart ile (avatar dosya):**
```bash
curl -X PUT http://localhost:8080/v1/admin/users/USER_ID \
  -H "Authorization: Bearer ADMIN_TOKEN" \
  -F "email=new@example.com" \
  -F "user_name=newname" \
  -F "roles=admin,user" \
  -F "avatar=@/path/to/new-photo.jpg"
```

**Response:**
```json
{
  "message": "User updated successfully",
  "user": {
    "id": "user-uuid",
    "username": "newname",
    "email": "new@example.com",
    "avatar": "/uploads/avatars/user-uuid_1707012346.jpg",
    "roles": [
      {"name": "admin"},
      {"name": "user"}
    ],
    "updated_at": "2026-02-04T..."
  }
}
```

---

## 🎯 Form Fields

### Create User (POST)

| Field | Type | Required | Açıklama |
|-------|------|----------|----------|
| `email` | string | ✅ | Email adresi |
| `password` | string | ✅ | Şifre (min 6 karakter) |
| `user_name` | string | ✅ | Kullanıcı adı |
| `email_verified` | boolean | ❌ | Email doğrulanmış mı? (true/false) |
| `roles` | string | ❌ | Roller (comma separated: "admin,user") |
| `avatar` | file | ❌ | Avatar dosyası (max 5MB, jpg/png/gif/webp) |

### Update User (PUT)

| Field | Type | Required | Açıklama |
|-------|------|----------|----------|
| `email` | string | ❌ | Yeni email |
| `password` | string | ❌ | Yeni şifre |
| `user_name` | string | ❌ | Yeni kullanıcı adı |
| `email_verified` | boolean | ❌ | Email doğrulama durumu |
| `roles` | string | ❌ | Yeni roller (comma separated) |
| `avatar` | file | ❌ | Yeni avatar dosyası |

**Not:** Tüm alanlar optional, sadece güncellemek istediklerinizi gönderin.

---

## 💻 Frontend Kullanımı

### HTML Form - Yeni Kullanıcı Oluştur

```html
<form id="createUserForm">
  <input type="email" name="email" required placeholder="Email">
  <input type="password" name="password" required placeholder="Password">
  <input type="text" name="user_name" required placeholder="Username">
  
  <label>
    <input type="checkbox" name="email_verified" value="true">
    Email Verified
  </label>
  
  <select name="roles" multiple>
    <option value="admin">Admin</option>
    <option value="user">User</option>
  </select>
  
  <input type="file" name="avatar" accept="image/*">
  
  <button type="submit">Create User</button>
</form>

<script>
document.getElementById('createUserForm').onsubmit = async (e) => {
  e.preventDefault();
  
  const formData = new FormData(e.target);
  
  // Roles'ü comma separated yap
  const rolesSelect = e.target.roles;
  const selectedRoles = Array.from(rolesSelect.selectedOptions).map(opt => opt.value);
  formData.set('roles', selectedRoles.join(','));
  
  const token = localStorage.getItem('admin_token');
  
  const response = await fetch('http://localhost:8080/v1/admin/users', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`
    },
    body: formData
  });
  
  const data = await response.json();
  
  if (response.ok) {
    console.log('User created:', data);
    alert('User created successfully!');
    if (data.avatar) {
      console.log('Avatar URL:', data.avatar);
    }
  } else {
    alert('Error: ' + data.error);
  }
};
</script>
```

### React - Kullanıcı Güncelle

```jsx
import { useState } from 'react';

function UpdateUserForm({ userId }) {
  const [formData, setFormData] = useState({
    email: '',
    user_name: '',
    password: '',
    email_verified: false,
    roles: [],
    avatar: null
  });
  
  const handleSubmit = async (e) => {
    e.preventDefault();
    
    const data = new FormData();
    
    if (formData.email) data.append('email', formData.email);
    if (formData.user_name) data.append('user_name', formData.user_name);
    if (formData.password) data.append('password', formData.password);
    if (formData.email_verified) data.append('email_verified', 'true');
    if (formData.roles.length > 0) data.append('roles', formData.roles.join(','));
    if (formData.avatar) data.append('avatar', formData.avatar);
    
    const token = localStorage.getItem('admin_token');
    
    try {
      const response = await fetch(`http://localhost:8080/v1/admin/users/${userId}`, {
        method: 'PUT',
        headers: {
          'Authorization': `Bearer ${token}`
        },
        body: data
      });
      
      const result = await response.json();
      
      if (response.ok) {
        console.log('User updated:', result.user);
        alert('User updated successfully!');
      } else {
        alert('Error: ' + result.error);
      }
    } catch (error) {
      console.error('Update failed:', error);
    }
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <input 
        type="email" 
        placeholder="Email"
        value={formData.email}
        onChange={(e) => setFormData({...formData, email: e.target.value})}
      />
      
      <input 
        type="text" 
        placeholder="Username"
        value={formData.user_name}
        onChange={(e) => setFormData({...formData, user_name: e.target.value})}
      />
      
      <input 
        type="password" 
        placeholder="New Password"
        value={formData.password}
        onChange={(e) => setFormData({...formData, password: e.target.value})}
      />
      
      <label>
        <input 
          type="checkbox"
          checked={formData.email_verified}
          onChange={(e) => setFormData({...formData, email_verified: e.target.checked})}
        />
        Email Verified
      </label>
      
      <select 
        multiple
        value={formData.roles}
        onChange={(e) => setFormData({
          ...formData, 
          roles: Array.from(e.target.selectedOptions).map(opt => opt.value)
        })}
      >
        <option value="admin">Admin</option>
        <option value="user">User</option>
      </select>
      
      <input 
        type="file" 
        accept="image/*"
        onChange={(e) => setFormData({...formData, avatar: e.target.files[0]})}
      />
      
      <button type="submit">Update User</button>
    </form>
  );
}
```

### Vue.js - Yeni Kullanıcı Oluştur

```vue
<template>
  <form @submit.prevent="createUser">
    <input v-model="formData.email" type="email" required placeholder="Email">
    <input v-model="formData.password" type="password" required placeholder="Password">
    <input v-model="formData.user_name" type="text" required placeholder="Username">
    
    <label>
      <input v-model="formData.email_verified" type="checkbox">
      Email Verified
    </label>
    
    <select v-model="formData.roles" multiple>
      <option value="admin">Admin</option>
      <option value="user">User</option>
    </select>
    
    <input type="file" @change="handleFileChange" accept="image/*">
    
    <button type="submit">Create User</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      formData: {
        email: '',
        password: '',
        user_name: '',
        email_verified: false,
        roles: [],
        avatar: null
      }
    }
  },
  methods: {
    handleFileChange(e) {
      this.formData.avatar = e.target.files[0];
    },
    
    async createUser() {
      const data = new FormData();
      
      data.append('email', this.formData.email);
      data.append('password', this.formData.password);
      data.append('user_name', this.formData.user_name);
      data.append('email_verified', this.formData.email_verified ? 'true' : 'false');
      
      if (this.formData.roles.length > 0) {
        data.append('roles', this.formData.roles.join(','));
      }
      
      if (this.formData.avatar) {
        data.append('avatar', this.formData.avatar);
      }
      
      const token = localStorage.getItem('admin_token');
      
      try {
        const response = await fetch('http://localhost:8080/v1/admin/users', {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${token}`
          },
          body: data
        });
        
        const result = await response.json();
        
        if (response.ok) {
          console.log('User created:', result);
          alert('User created successfully!');
          this.$emit('userCreated', result);
        } else {
          alert('Error: ' + result.error);
        }
      } catch (error) {
        console.error('Error:', error);
      }
    }
  }
}
</script>
```

---

## 🧪 Test Örnekleri

### Test 1: Yeni Kullanıcı + Avatar Oluştur

```bash
# Admin token al
curl -X POST http://localhost:8080/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@gauth.local","password":"Admin@123"}'

# Token'ı kaydet
TOKEN="eyJhbGci..."

# Yeni kullanıcı oluştur (avatar ile)
curl -X POST http://localhost:8080/v1/admin/users \
  -H "Authorization: Bearer $TOKEN" \
  -F "email=newuser@example.com" \
  -F "password=NewUser123!" \
  -F "user_name=newuser" \
  -F "email_verified=true" \
  -F "roles=user" \
  -F "avatar=@./user-photo.jpg"

# Response'da avatar URL göreceksiniz!
```

### Test 2: Kullanıcı Güncelle + Yeni Avatar

```bash
USER_ID="user-uuid-here"

curl -X PUT http://localhost:8080/v1/admin/users/$USER_ID \
  -H "Authorization: Bearer $TOKEN" \
  -F "email=updated@example.com" \
  -F "user_name=updatedname" \
  -F "roles=admin,user" \
  -F "avatar=@./new-avatar.jpg"
```

### Test 3: Sadece Avatar Değiştir

```bash
# Diğer alanları göndermeden sadece avatar
curl -X PUT http://localhost:8080/v1/admin/users/$USER_ID \
  -H "Authorization: Bearer $TOKEN" \
  -F "avatar=@./profile-pic.jpg"
```

### Test 4: Avatar Olmadan Güncelle

```bash
# Avatar olmadan da güncelleme yapabilirsiniz
curl -X PUT http://localhost:8080/v1/admin/users/$USER_ID \
  -H "Authorization: Bearer $TOKEN" \
  -F "email=another@example.com" \
  -F "user_name=anothername"
```

---

## 📊 Özellikler

### ✅ Create User
- **Multipart/form-data** ile avatar yükleme
- Email, password, username **required**
- Roles optional (comma separated: "admin,user")
- Email verified optional (true/false)
- Avatar optional (max 5MB)
- **Tek request**te hem kullanıcı hem avatar oluşturulur

### ✅ Update User
- **Hem JSON hem multipart** destekliyor
- Tüm alanlar optional
- Avatar dosya ile veya URL ile güncellenebilir
- Eski avatar otomatik silinir (local ise)
- OAuth avatar'ları korunur

### ✅ Avatar Validasyonu
- Format: JPG, JPEG, PNG, GIF, WebP
- Maksimum boyut: 5MB
- Otomatik dosya ismi: `{user_id}_{timestamp}.{ext}`

---

## 🔄 Content-Type Desteği

### Create User
```
Content-Type: multipart/form-data
```

### Update User
```
Content-Type: application/json  (JSON için)
Content-Type: multipart/form-data  (Avatar upload için)
```

Handler otomatik olarak Content-Type'a göre parse eder!

---

## ⚠️ Önemli Notlar

### 1. Roles Format

**Multipart:**
```
roles=admin,user
```

**JSON:**
```json
{
  "roles": ["admin", "user"]
}
```

### 2. Boolean Fields

**Multipart:**
```
email_verified=true
```

**JSON:**
```json
{
  "email_verified": true
}
```

### 3. Avatar Önceliği

1. Dosya upload (multipart) → En yüksek öncelik
2. Avatar URL (JSON) → Dosya yoksa
3. Mevcut avatar → Değişiklik yoksa

### 4. Eski Avatar Temizleme

```go
// Otomatik temizlik
if user.Avatar != "" && strings.HasPrefix(user.Avatar, "/uploads/") {
    os.Remove("." + user.Avatar)  // Eski local dosya silinir
}

// OAuth avatar'lar korunur
// https://... ile başlayanlar silinmez
```

---

## ✅ Özet

### Artık Yapabilirsiniz

1. ✅ **Yeni kullanıcı oluştururken avatar yükleyin**
2. ✅ **Kullanıcı güncellerken avatar değiştirin**
3. ✅ **Hem JSON hem multipart desteği**
4. ✅ **Tek request'te tüm işlemler**
5. ✅ **Otomatik dosya temizleme**
6. ✅ **Validation ve error handling**

### Build Durumu

```bash
✅ go build -o main .
✅ Build successful
✅ CreateUser multipart destekliyor
✅ UpdateUser multipart + JSON destekliyor
```

### Test Edin

```bash
# Uygulamayı başlat
./main

# Yeni kullanıcı + avatar
curl -X POST http://localhost:8080/v1/admin/users \
  -H "Authorization: Bearer TOKEN" \
  -F "email=test@example.com" \
  -F "password=Test123!" \
  -F "user_name=testuser" \
  -F "avatar=@photo.jpg"
```

**Artık user create ve update'te avatar yükleyebilirsiniz! 🎉**
