first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:35:24 +03:00
commit bbbf76b184
592 changed files with 246870 additions and 0 deletions

View File

@@ -0,0 +1,573 @@
# 🎉 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! 🎉**