905 lines
19 KiB
Markdown
905 lines
19 KiB
Markdown
# Authentication API Documentation
|
||
|
||
Bu doküman, Django REST API'nin authentication endpoint'lerini ve kullanım örneklerini içerir.
|
||
|
||
## 📋 İçindekiler
|
||
|
||
1. [Genel Bilgiler](#genel-bilgiler)
|
||
2. [Registration (Kayıt)](#registration-kayıt)
|
||
3. [Email Activation (Aktivasyon)](#email-activation-aktivasyon)
|
||
4. [Login (Giriş)](#login-giriş)
|
||
5. [Token Refresh](#token-refresh)
|
||
6. [Social Authentication](#social-authentication)
|
||
7. [User Profile](#user-profile)
|
||
8. [Password Reset](#password-reset)
|
||
9. [Frontend Entegrasyonu](#frontend-entegrasyonu)
|
||
10. [Error Handling](#error-handling)
|
||
|
||
---
|
||
|
||
## Genel Bilgiler
|
||
|
||
**Base URL:** `http://localhost:8000/api/v1/`
|
||
|
||
**Authentication:** JWT Bearer Token
|
||
```
|
||
Authorization: Bearer <access_token>
|
||
```
|
||
|
||
**Content-Type:** `application/json`
|
||
|
||
### Rate Limiting
|
||
- **Anonymous users:** 100 requests/hour
|
||
- **Authenticated users:** 1000 requests/hour
|
||
|
||
---
|
||
|
||
## Registration (Kayıt)
|
||
|
||
### Endpoint
|
||
```
|
||
POST /api/v1/auth/users/
|
||
```
|
||
|
||
### Request Body
|
||
```json
|
||
{
|
||
"email": "user@example.com",
|
||
"password": "StrongP@ssw0rd123",
|
||
"re_password": "StrongP@ssw0rd123",
|
||
"first_name": "Ali",
|
||
"last_name": "Veli"
|
||
}
|
||
```
|
||
|
||
### Response (201 Created)
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"email": "user@example.com",
|
||
"first_name": "Ali",
|
||
"last_name": "Veli"
|
||
}
|
||
```
|
||
|
||
### Önemli Notlar
|
||
- Kullanıcı oluşturulur ancak **`is_active=False`** olarak ayarlanır
|
||
- Aktivasyon emaili otomatik gönderilir
|
||
- Kullanıcı email aktivasyonu yapmadan login olamaz
|
||
- Password minimum 8 karakter olmalı ve güçlü olmalı
|
||
|
||
### Curl Example
|
||
```bash
|
||
curl -X POST http://localhost:8000/api/v1/auth/users/ \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"email": "user@example.com",
|
||
"password": "StrongP@ssw0rd123",
|
||
"re_password": "StrongP@ssw0rd123",
|
||
"first_name": "Ali",
|
||
"last_name": "Veli"
|
||
}'
|
||
```
|
||
|
||
---
|
||
|
||
## Email Activation (Aktivasyon)
|
||
|
||
### Endpoint
|
||
```
|
||
POST /api/v1/auth/users/activation/
|
||
```
|
||
|
||
### Request Body
|
||
```json
|
||
{
|
||
"uid": "MQ",
|
||
"token": "c4h7vu-a8f3d2e1c4b5a6d7e8f9g0h1"
|
||
}
|
||
```
|
||
|
||
### Response (204 No Content)
|
||
Başarılı aktivasyon sonrası response body boş döner.
|
||
|
||
### Önemli Notlar
|
||
- `uid` ve `token` aktivasyon emailindeki linkten alınır
|
||
- Token 24 saat geçerlidir
|
||
- Başarılı aktivasyon sonrası `is_active=True` olur
|
||
- Kullanıcı artık login olabilir
|
||
|
||
### Email Link Format
|
||
```
|
||
http://localhost:3000/auth/activate/{uid}/{token}/
|
||
```
|
||
|
||
Frontend bu linki yakalayıp backend'e POST request yapmalı.
|
||
|
||
### Curl Example
|
||
```bash
|
||
curl -X POST http://localhost:8000/api/v1/auth/users/activation/ \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"uid": "MQ",
|
||
"token": "c4h7vu-a8f3d2e1c4b5a6d7e8f9g0h1"
|
||
}'
|
||
```
|
||
|
||
### Resend Activation Email
|
||
```
|
||
POST /api/v1/auth/users/resend_activation/
|
||
```
|
||
|
||
Request Body:
|
||
```json
|
||
{
|
||
"email": "user@example.com"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Login (Giriş)
|
||
|
||
### Endpoint
|
||
```
|
||
POST /api/v1/auth/jwt/create/
|
||
```
|
||
|
||
### Request Body
|
||
```json
|
||
{
|
||
"email": "user@example.com",
|
||
"password": "StrongP@ssw0rd123"
|
||
}
|
||
```
|
||
|
||
### Response (200 OK)
|
||
```json
|
||
{
|
||
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||
}
|
||
```
|
||
|
||
### Token Bilgileri
|
||
- **Access Token:** 60 dakika geçerli
|
||
- **Refresh Token:** 7 gün geçerli
|
||
- Token rotation aktif (refresh kullanıldığında yeni refresh token döner)
|
||
|
||
### Önemli Notlar
|
||
- Kullanıcı `is_active=False` ise login başarısız olur
|
||
- Hatalı email/password için 401 Unauthorized döner
|
||
|
||
### Curl Example
|
||
```bash
|
||
curl -X POST http://localhost:8000/api/v1/auth/jwt/create/ \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"email": "user@example.com",
|
||
"password": "StrongP@ssw0rd123"
|
||
}'
|
||
```
|
||
|
||
### Error Response (401 Unauthorized)
|
||
```json
|
||
{
|
||
"detail": "No active account found with the given credentials"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Token Refresh
|
||
|
||
### Endpoint
|
||
```
|
||
POST /api/v1/auth/jwt/refresh/
|
||
```
|
||
|
||
### Request Body
|
||
```json
|
||
{
|
||
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||
}
|
||
```
|
||
|
||
### Response (200 OK)
|
||
```json
|
||
{
|
||
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||
}
|
||
```
|
||
|
||
### Önemli Notlar
|
||
- Yeni access token ve yeni refresh token döner (rotation)
|
||
- Eski refresh token blacklist'e eklenir
|
||
- Refresh token expire olduysa 401 döner
|
||
|
||
### Curl Example
|
||
```bash
|
||
curl -X POST http://localhost:8000/api/v1/auth/jwt/refresh/ \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||
}'
|
||
```
|
||
|
||
---
|
||
|
||
## Social Authentication
|
||
|
||
### Supported Providers
|
||
- **Google:** `google-oauth2`
|
||
- **GitHub:** `github`
|
||
- **Facebook:** `facebook`
|
||
|
||
### Endpoint
|
||
```
|
||
POST /api/v1/auth/social/<provider>/
|
||
```
|
||
|
||
### Request Body
|
||
```json
|
||
{
|
||
"access_token": "ya29.a0AfH6SMBx..."
|
||
}
|
||
```
|
||
|
||
### Response (200 OK)
|
||
```json
|
||
{
|
||
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||
"user": {
|
||
"id": 1,
|
||
"email": "user@example.com",
|
||
"first_name": "Ali",
|
||
"last_name": "Veli",
|
||
"is_active": true,
|
||
"date_joined": "2025-12-12T21:30:00Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
### Önemli Notlar
|
||
- Social login ile gelen kullanıcılar **otomatik aktif** (`is_active=True`)
|
||
- Email aktivasyon gerekmez
|
||
- Kullanıcı yoksa otomatik oluşturulur
|
||
- Provider'dan email alınamazsa hata döner
|
||
|
||
### Google OAuth2 Example
|
||
|
||
#### 1. Frontend'de Google OAuth
|
||
```javascript
|
||
// Google OAuth2 ile token al
|
||
const googleUser = await gapi.auth2.getAuthInstance().signIn();
|
||
const accessToken = googleUser.getAuthResponse().access_token;
|
||
|
||
// Backend'e gönder
|
||
const response = await fetch('http://localhost:8000/api/v1/auth/social/google-oauth2/', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({
|
||
access_token: accessToken
|
||
})
|
||
});
|
||
|
||
const data = await response.json();
|
||
// data.access, data.refresh, data.user
|
||
```
|
||
|
||
#### 2. Curl Example
|
||
```bash
|
||
curl -X POST http://localhost:8000/api/v1/auth/social/google-oauth2/ \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"access_token": "ya29.a0AfH6SMBx..."
|
||
}'
|
||
```
|
||
|
||
### GitHub OAuth2 Example
|
||
```bash
|
||
curl -X POST http://localhost:8000/api/v1/auth/social/github/ \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"access_token": "gho_16C7e42F292c6912E7710c838347Ae178B4a"
|
||
}'
|
||
```
|
||
|
||
### Error Responses
|
||
|
||
**Invalid Provider (400)**
|
||
```json
|
||
{
|
||
"error": "Invalid provider. Must be one of: google-oauth2, github, facebook"
|
||
}
|
||
```
|
||
|
||
**Missing Token (400)**
|
||
```json
|
||
{
|
||
"error": "access_token is required"
|
||
}
|
||
```
|
||
|
||
**Authentication Failed (401)**
|
||
```json
|
||
{
|
||
"error": "Authentication failed. Invalid token."
|
||
}
|
||
```
|
||
|
||
**Email Not Provided (403)**
|
||
```json
|
||
{
|
||
"error": "Authentication forbidden. Email not provided by provider or permission denied."
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## User Profile
|
||
|
||
### Get Current User
|
||
```
|
||
GET /api/v1/auth/users/me/
|
||
```
|
||
|
||
**Headers:**
|
||
```
|
||
Authorization: Bearer <access_token>
|
||
```
|
||
|
||
**Response (200 OK):**
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"email": "user@example.com",
|
||
"first_name": "Ali",
|
||
"last_name": "Veli",
|
||
"is_active": true,
|
||
"date_joined": "2025-12-12T21:30:00Z"
|
||
}
|
||
```
|
||
|
||
### Update Current User
|
||
```
|
||
PATCH /api/v1/auth/users/me/
|
||
```
|
||
|
||
**Request Body:**
|
||
```json
|
||
{
|
||
"first_name": "Ahmet",
|
||
"last_name": "Yılmaz"
|
||
}
|
||
```
|
||
|
||
### Curl Example
|
||
```bash
|
||
curl -X GET http://localhost:8000/api/v1/auth/users/me/ \
|
||
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||
```
|
||
|
||
---
|
||
|
||
## Password Reset
|
||
|
||
### 1. Request Password Reset
|
||
```
|
||
POST /api/v1/auth/users/reset_password/
|
||
```
|
||
|
||
**Request Body:**
|
||
```json
|
||
{
|
||
"email": "user@example.com"
|
||
}
|
||
```
|
||
|
||
**Response (204 No Content)**
|
||
|
||
Email gönderilir, link formatı:
|
||
```
|
||
http://localhost:3000/auth/password/reset/confirm/{uid}/{token}/
|
||
```
|
||
|
||
### 2. Confirm Password Reset
|
||
```
|
||
POST /api/v1/auth/users/reset_password_confirm/
|
||
```
|
||
|
||
**Request Body:**
|
||
```json
|
||
{
|
||
"uid": "MQ",
|
||
"token": "c4h7vu-a8f3d2e1c4b5a6d7e8f9g0h1",
|
||
"new_password": "NewStrongP@ssw0rd123",
|
||
"re_new_password": "NewStrongP@ssw0rd123"
|
||
}
|
||
```
|
||
|
||
**Response (204 No Content)**
|
||
|
||
---
|
||
|
||
## Frontend Entegrasyonu
|
||
|
||
### Nuxt.js 3 Example
|
||
|
||
#### 1. Composable: `useAuth.ts`
|
||
```typescript
|
||
// composables/useAuth.ts
|
||
export const useAuth = () => {
|
||
const config = useRuntimeConfig();
|
||
const accessToken = useCookie('access_token');
|
||
const refreshToken = useCookie('refresh_token');
|
||
|
||
const register = async (userData: {
|
||
email: string;
|
||
password: string;
|
||
re_password: string;
|
||
first_name: string;
|
||
last_name: string;
|
||
}) => {
|
||
const { data, error } = await useFetch(`${config.public.apiBase}/auth/users/`, {
|
||
method: 'POST',
|
||
body: userData,
|
||
});
|
||
return { data, error };
|
||
};
|
||
|
||
const login = async (email: string, password: string) => {
|
||
const { data, error } = await useFetch(`${config.public.apiBase}/auth/jwt/create/`, {
|
||
method: 'POST',
|
||
body: { email, password },
|
||
});
|
||
|
||
if (data.value) {
|
||
accessToken.value = data.value.access;
|
||
refreshToken.value = data.value.refresh;
|
||
}
|
||
|
||
return { data, error };
|
||
};
|
||
|
||
const socialLogin = async (provider: string, accessTokenValue: string) => {
|
||
const { data, error } = await useFetch(
|
||
`${config.public.apiBase}/auth/social/${provider}/`,
|
||
{
|
||
method: 'POST',
|
||
body: { access_token: accessTokenValue },
|
||
}
|
||
);
|
||
|
||
if (data.value) {
|
||
accessToken.value = data.value.access;
|
||
refreshToken.value = data.value.refresh;
|
||
}
|
||
|
||
return { data, error };
|
||
};
|
||
|
||
const getUser = async () => {
|
||
if (!accessToken.value) return null;
|
||
|
||
const { data } = await useFetch(`${config.public.apiBase}/auth/users/me/`, {
|
||
headers: {
|
||
Authorization: `Bearer ${accessToken.value}`,
|
||
},
|
||
});
|
||
|
||
return data.value;
|
||
};
|
||
|
||
const logout = () => {
|
||
accessToken.value = null;
|
||
refreshToken.value = null;
|
||
};
|
||
|
||
return {
|
||
register,
|
||
login,
|
||
socialLogin,
|
||
getUser,
|
||
logout,
|
||
accessToken,
|
||
refreshToken,
|
||
};
|
||
};
|
||
```
|
||
|
||
#### 2. Register Page: `pages/auth/register.vue`
|
||
```vue
|
||
<template>
|
||
<div>
|
||
<h1>Register</h1>
|
||
<form @submit.prevent="handleRegister">
|
||
<input v-model="form.email" type="email" placeholder="Email" required />
|
||
<input v-model="form.first_name" placeholder="First Name" />
|
||
<input v-model="form.last_name" placeholder="Last Name" />
|
||
<input v-model="form.password" type="password" placeholder="Password" required />
|
||
<input v-model="form.re_password" type="password" placeholder="Confirm Password" required />
|
||
<button type="submit">Register</button>
|
||
</form>
|
||
<p v-if="message">{{ message }}</p>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
const { register } = useAuth();
|
||
const form = ref({
|
||
email: '',
|
||
password: '',
|
||
re_password: '',
|
||
first_name: '',
|
||
last_name: '',
|
||
});
|
||
const message = ref('');
|
||
|
||
const handleRegister = async () => {
|
||
const { data, error } = await register(form.value);
|
||
|
||
if (error.value) {
|
||
message.value = 'Registration failed';
|
||
} else {
|
||
message.value = 'Registration successful! Please check your email to activate your account.';
|
||
}
|
||
};
|
||
</script>
|
||
```
|
||
|
||
#### 3. Activation Page: `pages/auth/activate/[uid]/[token].vue`
|
||
```vue
|
||
<template>
|
||
<div>
|
||
<h1>Account Activation</h1>
|
||
<p v-if="loading">Activating your account...</p>
|
||
<p v-else-if="success">✅ Account activated successfully! You can now login.</p>
|
||
<p v-else-if="error">❌ Activation failed. Link may be expired.</p>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
const route = useRoute();
|
||
const config = useRuntimeConfig();
|
||
|
||
const loading = ref(true);
|
||
const success = ref(false);
|
||
const error = ref(false);
|
||
|
||
onMounted(async () => {
|
||
const { uid, token } = route.params;
|
||
|
||
try {
|
||
await $fetch(`${config.public.apiBase}/auth/users/activation/`, {
|
||
method: 'POST',
|
||
body: { uid, token },
|
||
});
|
||
success.value = true;
|
||
} catch (e) {
|
||
error.value = true;
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
});
|
||
</script>
|
||
```
|
||
|
||
#### 4. Login Page: `pages/auth/login.vue`
|
||
```vue
|
||
<template>
|
||
<div>
|
||
<h1>Login</h1>
|
||
<form @submit.prevent="handleLogin">
|
||
<input v-model="email" type="email" placeholder="Email" required />
|
||
<input v-model="password" type="password" placeholder="Password" required />
|
||
<button type="submit">Login</button>
|
||
</form>
|
||
|
||
<div class="social-login">
|
||
<button @click="handleGoogleLogin">Login with Google</button>
|
||
<button @click="handleGithubLogin">Login with GitHub</button>
|
||
</div>
|
||
|
||
<p v-if="error">{{ error }}</p>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
const { login, socialLogin } = useAuth();
|
||
const router = useRouter();
|
||
|
||
const email = ref('');
|
||
const password = ref('');
|
||
const error = ref('');
|
||
|
||
const handleLogin = async () => {
|
||
const { data, error: loginError } = await login(email.value, password.value);
|
||
|
||
if (loginError.value) {
|
||
error.value = 'Login failed. Please check your credentials.';
|
||
} else {
|
||
router.push('/dashboard');
|
||
}
|
||
};
|
||
|
||
const handleGoogleLogin = async () => {
|
||
// Google OAuth2 implementation
|
||
// Use @nuxtjs/google-oauth2 or similar
|
||
const googleToken = await getGoogleAccessToken(); // Your implementation
|
||
|
||
const { data, error: socialError } = await socialLogin('google-oauth2', googleToken);
|
||
|
||
if (!socialError.value) {
|
||
router.push('/dashboard');
|
||
}
|
||
};
|
||
|
||
const handleGithubLogin = async () => {
|
||
// GitHub OAuth2 implementation
|
||
const githubToken = await getGithubAccessToken(); // Your implementation
|
||
|
||
const { data, error: socialError } = await socialLogin('github', githubToken);
|
||
|
||
if (!socialError.value) {
|
||
router.push('/dashboard');
|
||
}
|
||
};
|
||
</script>
|
||
```
|
||
|
||
### Next.js 14 Example
|
||
|
||
#### 1. Auth Context: `context/AuthContext.tsx`
|
||
```typescript
|
||
'use client';
|
||
|
||
import { createContext, useContext, useState, useEffect } from 'react';
|
||
|
||
interface User {
|
||
id: number;
|
||
email: string;
|
||
first_name: string;
|
||
last_name: string;
|
||
}
|
||
|
||
interface AuthContextType {
|
||
user: User | null;
|
||
login: (email: string, password: string) => Promise<void>;
|
||
logout: () => void;
|
||
register: (userData: any) => Promise<void>;
|
||
}
|
||
|
||
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
||
|
||
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||
const [user, setUser] = useState<User | null>(null);
|
||
const [accessToken, setAccessToken] = useState<string | null>(null);
|
||
|
||
useEffect(() => {
|
||
// Load token from localStorage
|
||
const token = localStorage.getItem('access_token');
|
||
if (token) {
|
||
setAccessToken(token);
|
||
fetchUser(token);
|
||
}
|
||
}, []);
|
||
|
||
const fetchUser = async (token: string) => {
|
||
try {
|
||
const response = await fetch('http://localhost:8000/api/v1/auth/users/me/', {
|
||
headers: {
|
||
'Authorization': `Bearer ${token}`,
|
||
},
|
||
});
|
||
const data = await response.json();
|
||
setUser(data);
|
||
} catch (error) {
|
||
console.error('Failed to fetch user', error);
|
||
}
|
||
};
|
||
|
||
const login = async (email: string, password: string) => {
|
||
const response = await fetch('http://localhost:8000/api/v1/auth/jwt/create/', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({ email, password }),
|
||
});
|
||
|
||
if (!response.ok) {
|
||
throw new Error('Login failed');
|
||
}
|
||
|
||
const data = await response.json();
|
||
localStorage.setItem('access_token', data.access);
|
||
localStorage.setItem('refresh_token', data.refresh);
|
||
setAccessToken(data.access);
|
||
await fetchUser(data.access);
|
||
};
|
||
|
||
const logout = () => {
|
||
localStorage.removeItem('access_token');
|
||
localStorage.removeItem('refresh_token');
|
||
setAccessToken(null);
|
||
setUser(null);
|
||
};
|
||
|
||
const register = async (userData: any) => {
|
||
const response = await fetch('http://localhost:8000/api/v1/auth/users/', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify(userData),
|
||
});
|
||
|
||
if (!response.ok) {
|
||
throw new Error('Registration failed');
|
||
}
|
||
};
|
||
|
||
return (
|
||
<AuthContext.Provider value={{ user, login, logout, register }}>
|
||
{children}
|
||
</AuthContext.Provider>
|
||
);
|
||
}
|
||
|
||
export const useAuth = () => {
|
||
const context = useContext(AuthContext);
|
||
if (context === undefined) {
|
||
throw new Error('useAuth must be used within an AuthProvider');
|
||
}
|
||
return context;
|
||
};
|
||
```
|
||
|
||
---
|
||
|
||
## Error Handling
|
||
|
||
### Common Error Codes
|
||
|
||
| Status Code | Meaning | Common Causes |
|
||
|-------------|---------|---------------|
|
||
| 400 | Bad Request | Invalid data, validation errors |
|
||
| 401 | Unauthorized | Invalid credentials, expired token |
|
||
| 403 | Forbidden | Account not activated, permission denied |
|
||
| 404 | Not Found | Endpoint doesn't exist |
|
||
| 429 | Too Many Requests | Rate limit exceeded |
|
||
| 500 | Internal Server Error | Server-side error |
|
||
|
||
### Error Response Format
|
||
```json
|
||
{
|
||
"detail": "Error message here",
|
||
"field_name": ["Field-specific error"]
|
||
}
|
||
```
|
||
|
||
### Example: Registration Validation Error
|
||
```json
|
||
{
|
||
"email": ["A user with that email already exists."],
|
||
"password": ["This password is too common."]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Testing with Postman/Insomnia
|
||
|
||
### 1. Register
|
||
```
|
||
POST http://localhost:8000/api/v1/auth/users/
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"email": "test@example.com",
|
||
"password": "TestP@ssw0rd123",
|
||
"re_password": "TestP@ssw0rd123",
|
||
"first_name": "Test",
|
||
"last_name": "User"
|
||
}
|
||
```
|
||
|
||
### 2. Check Email (MailPit)
|
||
Open: `http://localhost:8025`
|
||
|
||
### 3. Activate Account
|
||
```
|
||
POST http://localhost:8000/api/v1/auth/users/activation/
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"uid": "MQ",
|
||
"token": "c4h7vu-a8f3d2e1c4b5a6d7e8f9g0h1"
|
||
}
|
||
```
|
||
|
||
### 4. Login
|
||
```
|
||
POST http://localhost:8000/api/v1/auth/jwt/create/
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"email": "test@example.com",
|
||
"password": "TestP@ssw0rd123"
|
||
}
|
||
```
|
||
|
||
### 5. Get User Profile
|
||
```
|
||
GET http://localhost:8000/api/v1/auth/users/me/
|
||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||
```
|
||
|
||
---
|
||
|
||
## Environment Variables
|
||
|
||
### Development (.env.dev)
|
||
```bash
|
||
DEBUG=True
|
||
SECRET_KEY=your-secret-key-here
|
||
ALLOWED_HOSTS=localhost,127.0.0.1
|
||
|
||
# Database
|
||
DATABASE_URL=sqlite:///db.sqlite3
|
||
|
||
# Email (MailPit)
|
||
EMAIL_HOST=localhost
|
||
EMAIL_PORT=1025
|
||
EMAIL_USE_TLS=False
|
||
|
||
# CORS
|
||
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173
|
||
```
|
||
|
||
### Production (.env.prod)
|
||
```bash
|
||
DEBUG=False
|
||
SECRET_KEY=your-production-secret-key
|
||
ALLOWED_HOSTS=yourdomain.com,api.yourdomain.com
|
||
|
||
# Database
|
||
DATABASE_URL=postgresql://user:pass@host:5432/dbname
|
||
|
||
# Email
|
||
EMAIL_HOST=smtp.gmail.com
|
||
EMAIL_PORT=587
|
||
EMAIL_USE_TLS=True
|
||
EMAIL_HOST_USER=your-email@gmail.com
|
||
EMAIL_HOST_PASSWORD=your-app-password
|
||
|
||
# Social Auth
|
||
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY=your-google-client-id
|
||
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET=your-google-client-secret
|
||
SOCIAL_AUTH_GITHUB_KEY=your-github-client-id
|
||
SOCIAL_AUTH_GITHUB_SECRET=your-github-client-secret
|
||
|
||
# CORS
|
||
CORS_ALLOWED_ORIGINS=https://yourdomain.com
|
||
```
|
||
|
||
---
|
||
|
||
## Support
|
||
|
||
Sorularınız için:
|
||
- GitHub Issues: [Your Repo]
|
||
- Email: support@yourdomain.com
|
||
- Documentation: [Your Docs URL]
|
||
|
||
---
|
||
|
||
**Last Updated:** 2025-12-12
|
||
**Version:** 1.0.0
|
||
|