Skip to content

Commit 81601eb

Browse files
committed
fix: Configuration and changing mistakes 🫠"
1 parent 3687714 commit 81601eb

20 files changed

+367
-119
lines changed

.env-example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ ALLOWED_HOSTS=localhost,127.0.0.1
1313
DJANGO_SETTINGS_MODULE=core.settings.development # default
1414

1515
#### JWT (RS256) private, public keys default ####
16-
PRIVATE_KEY_PATH=security_settings/private_key.pem
17-
PUBLIC_KEY_PATH=security_settings/public_key.pem
16+
PRIVATE_KEY_PATH=security/private_key.pem
17+
PUBLIC_KEY_PATH=security/public_key.pem
1818

1919
#### Django database environs sqlite3, postgres, mysql ####
2020
DATABASE_ENVIRON=sqlite3

.github/workflows/lint.yml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ on:
1111
- "master"
1212

1313
jobs:
14-
15-
build:
14+
lint:
1615
runs-on: ubuntu-latest
1716
strategy:
1817
matrix:
@@ -46,21 +45,20 @@ jobs:
4645
touch .env
4746
echo PRIVATE_KEY_PATH=$(pwd)/security/private_key.pem >> .env
4847
echo PUBLIC_KEY_PATH=$(pwd)/security/public_key.pem >> .env
49-
DJANGO_SETTINGS_MODULE=core.settings.development >> .env
48+
echo DJANGO_SETTINGS_MODULE=core.settings.development >> .env
5049
echo DATABASE_ENVIRON=sqlite3 >> .env
5150
52-
5351
- name: Check if .env has been updated
5452
run: cat .env
5553

5654
- name: Install Dependencies
5755
run: |
58-
pip install flake8
5956
python -m pip install --upgrade pip
6057
pip install -r requirements.txt
58+
pip install ruff
6159
62-
- name: Lint Code
63-
run: flake8 .
60+
- name: Run Ruff Linter
61+
run: ruff check .
6462

6563
- name: Clean up keys (Optional)
6664
run: |

README.md

Lines changed: 74 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,134 @@
11
![logo](logo.png)
2-
# Blog App
32

4-
Blog App — это веб-приложение на Django для создания, управления и просмотра блог-постов с аутентификацией через JWT-токены.
3+
# ✨ Blog Web App
54

6-
## Основные возможности
5+
**Blog Web App** — это современное веб-приложение на **Django**, позволяющее создавать 📝, редактировать ✏️ и просматривать 👀 блог-посты с безопасной аутентификацией через **JWT-токены**.
76

8-
- **Создание постов**: авторизированные пользователи могут добавлять и редактировать свои посты.
9-
- **Чтение постов**: все пользователи могут просматривать посты.
10-
- **Авторизация через JWT**: безопасная авторизация с использованием Access и Refresh токенов (Algorithm RS256).
7+
---
118

12-
## Стек технологий
9+
## 🚀 Основные возможности
1310

14-
- **Backend**: Django, Django REST Framework
15-
- **Аутентификация**: JWT (с использованием `djangorestframework-simplejwt`)
16-
- **База данных**: PostgreSQL (или SQLite для локальной разработки)
17-
- **Кэширование**: Django Cache (опционально, для оптимизации производительности)
11+
- 📝 **Создание постов**: авторизированные пользователи могут добавлять и редактировать свои посты.
12+
- 👥 **Чтение постов**: все пользователи могут просматривать записи.
13+
- 🔐 **Авторизация через JWT**: безопасная аутентификация с использованием Access и Refresh токенов (Algorithm **RS256**).
1814

19-
## Установка и запуск
15+
---
2016

21-
### Клонирование репозитория
17+
## 🛠️ Стек технологий
2218

23-
```bash
24-
git clone https://github.com/RustamovAkrom/Blog-2.git
25-
cd Blog-2
26-
```
19+
- **Backend**: Django, Django REST Framework
20+
- **Аутентификация**: JWT (`djangorestframework-simplejwt`)
21+
- **База данных**: PostgreSQL (или SQLite для локальной разработки)
22+
- **Кэширование**: Django Cache (опционально 🚀 для ускорения работы)
23+
24+
---
2725

28-
### Настройка виртуального окружения
26+
## ⚡ Быстрый старт
2927

30-
Создайте и активируйте виртуальное окружение:
28+
### 📥 Клонирование репозитория
29+
```bash
30+
git clone https://github.com/RustamovAkrom/Blog-Web-APP.git
31+
cd Blog-Web-APP
32+
```
3133

34+
### 🐍 Настройка виртуального окружения
3235
```bash
3336
python -m venv venv
3437
source venv/bin/activate # для Linux/macOS
35-
venv\Scripts\activate # для Windows
38+
venv\Scripts\activate # для Windows
3639
```
3740

38-
### Установка зависимостей
39-
40-
Установите необходимые зависимости:
41-
41+
### 📦 Установка зависимостей
4242
```bash
4343
pip install -r requirements.txt
4444
```
4545

46-
### Настройка переменных окружения
47-
48-
Создайте файл `.env` в корне проекта и добавьте туда настройки для базы данных и JWT. Пример:
49-
50-
```sh
51-
#!/bin/bash
46+
### ⚙️ Настройка переменных окружения
47+
Создайте файл `.env` в корне проекта и укажите настройки:
5248

49+
```bash
5350
SECRET_KEY=<your django secret key>
51+
DEBUG=True
52+
ALLOWED_HOSTS=localhost,127.0.0.1
53+
DJANGO_SETTINGS_MODULE=core.settings.development
5454

55-
DEBUG=True # default
56-
57-
ALLOWED_HOSTS=localhost,127.0.0.1 # default
58-
59-
# `core.settings.development` or `core.setting.production`
60-
DJANGO_SETTINGS_MODULE=core.settings.development # default
55+
PRIVATE_KEY_PATH=security_settings/private_key.pem
56+
PUBLIC_KEY_PATH=security_settings/public_key.pem
6157

62-
PRIVATE_KEY_PATH=security_settings/private_key.pem # default
63-
PUBLIC_KEY_PATH=security_settings/public_key.pem # default
58+
DATABASE_ENVIRON=sqlite
6459

65-
DATABASE_ENVIRON=sqlite # sqlite or postgres
66-
67-
# PostgreSQL configruations
6860
DATABASE_NAME=<your database name>
6961
DATABASE_USER=<your database user>
7062
DATABASE_PASSWORD=<your database password>
71-
DATABASE_HOST=localhost # default
72-
DATABASE_PORT=5432 # default
63+
DATABASE_HOST=localhost
64+
DATABASE_PORT=5432
7365

74-
ADMIN_USERNAME=admin # default
75-
ADMIN_PASSWORD=password # default
76-
ADMIN_EMAIL=admin@example.com # default
66+
ADMIN_USERNAME=admin
67+
ADMIN_PASSWORD=password
68+
ADMIN_EMAIL=admin@example.com
7769
```
7870

79-
### Применение миграций и создание суперпользователя
71+
---
72+
73+
## 🔑 Генерация RSA-ключей
8074

81-
Примените миграции и создайте суперпользователя для доступа к админ-панели:
75+
JWT с алгоритмом **RS256** требует приватный и публичный ключи.
76+
👉 Подробная инструкция: [docs/generate-rsa-keys-for-simple-jwt.md](docs/generate-rsa-keys-for-simple-jwt.md)
8277

78+
---
79+
80+
### 📚 Применение миграций и создание суперпользователя
8381
```bash
8482
python manage.py migrate
8583
python manage.py createadmin
8684
```
8785

88-
### Запуск сервера
89-
90-
Запустите сервер разработки:
91-
86+
### ▶️ Запуск сервера
9287
```bash
9388
python manage.py runserver
9489
```
9590

96-
Теперь ваше приложение доступно по адресу: `http://127.0.0.1:8000`
91+
Теперь приложение доступно по адресу:
92+
👉 `http://127.0.0.1:8000`
9793

98-
## Аутентификация через JWT
94+
---
9995

100-
Blog App использует JWT для аутентификации. При входе в систему клиент получает два токена:
101-
- **Access Token** — для доступа к защищённым маршрутам.
102-
- **Refresh Token** — для обновления Access Token.
96+
## 🔐 Аутентификация через JWT
10397

104-
<!-- ### Эндпоинты для аутентификации
98+
После входа пользователь получает два токена:
10599

106-
- **`/api/token/`** — получение Access и Refresh токенов (логин).
107-
- **`/api/token/refresh/`** — обновление Access Token с помощью Refresh Token.
108-
- **`/api/token/verify/`** — проверка действительности токена. -->
100+
- 🔑 **Access Token** — доступ к защищённым маршрутам
101+
- ♻️ **Refresh Token** — обновление Access Token
109102

110-
### Пример использования JWT
103+
Пример использования:
104+
```http
105+
Authorization: Bearer <access_token>
106+
```
111107

112-
1. Получите Access и Refresh токены с помощью `/api/token/`.
113-
2. Используйте Access Token для доступа к защищённым эндпоинтам, добавляя его в заголовок запросов:
108+
---
114109

115-
```http
116-
Authorization: Bearer <access_token>
117-
```
110+
## 📂 Структура проекта
118111

119-
3. Когда Access Token истекает, обновите его с помощью `/api/token/refresh/`, отправляя Refresh Token в теле запроса.
112+
- `apps/users` — управление пользователями и аутентификацией
113+
- `apps/blog` — блог-посты
114+
- `middleware` — JWT-middleware
115+
- `settings` — настройки Django, базы данных и кэша
120116

121-
<!-- ## API эндпоинты
117+
---
122118

123-
- **GET /api/posts/**: Просмотр всех постов
124-
- **POST /api/posts/**: Создание нового поста (только для авторизованных пользователей)
125-
- **GET /api/posts/<id>/**: Просмотр поста по ID
126-
- **PUT /api/posts/<id>/**: Обновление поста (только для автора)
127-
- **DELETE /api/posts/<id>/**: Удаление поста (только для автора) -->
119+
## ⚡ Кэширование
128120

129-
## Структура проекта
121+
Для ускорения работы Blog App можно использовать кэширование JWT-токенов.
130122

131-
- **apps/users**: Приложение для управления пользователями и аутентификацией.
132-
- **apps/posts**: Приложение для создания, редактирования и удаления блог-постов.
133-
- **middleware**: JWT Middleware для авторизации с использованием токенов.
134-
- **settings**: Файл настроек Django, включая конфигурацию базы данных и кэширования.
123+
---
135124

136-
## Кэширование
125+
## 📜 Лицензия
137126

138-
Для ускорения работы Blog App можно использовать кэширование JWT-токенов. Этот механизм позволяет кэшировать данные пользователей для быстрого доступа без необходимости каждый раз проверять токен.
127+
Проект распространяется по лицензии **MIT License**.
139128

140-
## Лицензия
129+
---
141130

142-
Этот проект лицензирован на условиях **MIT License**.
131+
## 📖 Документация
143132

144-
## Documentations: https://rustamovakrom.github.io/Blog-2/
133+
Подробная документация доступна здесь:
134+
👉 [Documentation](https://rustamovakrom.github.io/blog-web-app/)

apps/blog/migrations/0001_initial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 5.1.1 on 2024-11-13 12:31
1+
# Generated by Django 5.2.5 on 2025-08-22 21:17
22

33
from django.db import migrations, models
44

apps/blog/migrations/0002_initial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 5.1.1 on 2024-11-13 12:31
1+
# Generated by Django 5.2.5 on 2025-08-22 21:17
22

33
import django.db.models.deletion
44
from django.conf import settings

apps/users/migrations/0001_initial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 5.1.1 on 2024-11-13 12:31
1+
# Generated by Django 5.2.5 on 2025-08-22 21:17
22

33
import django.contrib.auth.models
44
import django.contrib.auth.validators

apps/users/models.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,20 @@ class User(TimestempedAbstractModel, AbstractUser):
99
email = models.EmailField(_("email address"), unique=True)
1010

1111
@property
12-
def post_count(self):
13-
return self.posts.count
12+
def post_count(self) -> int:
13+
"""Количество постов пользователя"""
14+
return getattr(self, "posts", None).count() if hasattr(self, "posts") else 0
1415

1516
def get_user_avatar_url(self) -> str:
16-
return str(self.profiles.avatar.url)
17+
"""Безопасно возвращает URL аватара"""
18+
if hasattr(self, "profiles") and self.profiles.avatar:
19+
return self.profiles.avatar.url
20+
return "/media/avatars/default/logo.png"
1721

1822
def get_user_bio(self) -> str:
19-
bio = str(self.profiles.bio)
20-
if bio:
21-
return bio
23+
"""Безопасно возвращает bio"""
24+
if hasattr(self, "profiles") and self.profiles.bio:
25+
return self.profiles.bio
2226
return ""
2327

2428
class Meta:
@@ -29,6 +33,13 @@ class Meta:
2933
def __str__(self) -> str:
3034
return self.username
3135

36+
def save(self, *args, **kwargs):
37+
"""Автоматически создаём профиль при сохранении юзера"""
38+
is_new = self.pk is None
39+
super().save(*args, **kwargs)
40+
if is_new and not hasattr(self, "profiles"):
41+
UserProfile.objects.create(user=self)
42+
3243

3344
class UserProfile(TimestempedAbstractModel):
3445
user = models.OneToOneField(
@@ -56,5 +67,8 @@ def __str__(self) -> str:
5667

5768
def save(self, *args, **kwargs):
5869
super().save(*args, **kwargs)
59-
60-
processor_iamge(self.avatar.path)
70+
if self.avatar: # обработка изображения только если оно реально есть
71+
try:
72+
processor_iamge(self.avatar.path)
73+
except (FileNotFoundError, ValueError):
74+
pass

apps/users/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
from pathlib import Path
12
from PIL import Image
23

34

45
def processor_iamge(img_path, width_size: int = 300, height_size: int = 300):
6+
if not Path(img_path).exists():
7+
return
8+
59
img = Image.open(img_path)
610
max_size = (width_size, height_size)
711
img.thumbnail(max_size, Image.LANCZOS)

core/config/jwt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
load_dotenv(os.path.join(BASE_DIR, ".env"))
1010

11-
with open(str(os.getenv("PRIVATE_KEY_PATH", "security/private_key")), "r") as f:
11+
with open(str(os.getenv("PRIVATE_KEY_PATH", "security/private_key.pem")), "r") as f:
1212
PRIVATE_KEY = f.read()
1313

1414
with open(str(os.getenv("PUBLIC_KEY_PATH", "security/public_key.pem")), "r") as f:

dev.py

Whitespace-only changes.

0 commit comments

Comments
 (0)