شرکت بورس ع.ش که بعد از کرونا مشتریهای زیادی پیدا کرده، با مشکلات جدیدی روبهرو شده!
زیاد شدن تعداد مشتریهای این شرکت بورس، باعث جلب توجه تعدادی از خرابکاران اینترنتی شده. این خرابکارها تصمیم گرفتند تا با حملههای **DDoS** به سایت این شرکت، آن را از دسترس خارج کنند و تنها به ازای گرفتن پولی هنگفت! از رئیس شرکت، دست از حمله بر میدارند.
شما باید به مدیر شرکت ع.ش کمک کنید تا با کمترین هزینه و با کمک دانش ملی و بومی! جلوی حملات این خرابکاران را بگیرد.
# پروژه اولیه
پروژه اولیه را از [این لینک](/contest/assignments/21629/download_problem_initial_project/76085/) دانلود کنید. ساختار فایلهای این پروژه به صورت زیر است:
<details class="brown">
<summary>
ساختار فایلها
</summary>
```
boors-va-corona
├── apps
│ ├── guard
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── __init__.py
│ │ ├── management
│ │ │ ├── commands
│ │ │ │ ├── init_guard.py
│ │ │ │ └── __init__.py
│ │ │ └── __init__.py
│ │ ├── middlewares.py
│ │ ├── migrations
│ │ ├── models.py
│ │ ├── urls.py
│ │ ├── utils.py
│ │ └── views.py
│ ├── __init__.py
│ └── market
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── codecup
│ ├── asgi.py
│ ├── __init__.py
│ ├── settings
│ │ ├── base.py
│ │ ├── development.py
│ │ ├── __init__.py
│ │ └── production.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── codecupdb.sqlite3
├── deploy
│ └── nginx
│ └── default.conf
├── docker-compose.yml
├── Dockerfile
├── manage.py
├── README.md
└── requirements.txt
```
</details>
<details class="brown">
<summary>راهاندازی پروژه</summary>
برای اجرای پروژه ابتدا باید تمام کتابخانههای مورد نیاز را با استفاده از دستور زیر اجرا کنید:
```
> pip install -r requirements.txt
```
برای اجرای خود پروژه هم میتوانید از دستور زیر استفاده کنید:
```
> python manage.py runserver
```
</details>
فایلهایی که شما باید در این پروژه تکمیل کنید همگی در اپ `guard` قرار دارند. نام این فایلها به صورت زیر است:
`middlewares.py`
`admin.py`
`models.py`
`init_guard.py`
<details class="green">
<summary>
فایل `models.py`
</summary>
در این فایل تمام مدلهای مورد نیاز برای پروژه از قبل تعریف شدهاند. در زیر به توضیح هر کدام از این مدلها میپردازیم:
### مدل `BlockedIp`
این مدل برای ذخیره کد آیپیها مسدود شده می باشد. این مدل یک فیلد `ban_time` دارد که اگر از زمان ساخت یک نمونه از این مدل، به مقدار `ban_time` بگذرد، آیپی موردنظر از حالت مسدود خارج میشود. توجه کنید که واحد `ban_time` به ثانیه است.
شما تنها کافیست دو متد `is_blocked` و `is_ip_blocked` را کامل کنید. متد `is_blocked` یک مقدار بولین برمیگرداند که آیا هنوز یک شئ `BlockedIp` معتبر هست یا نه. اگر معتبر بود مقدار `True` و اگر زمان `ban_time` به طور کامل گذشته باشد مقدار `False` برمیگرداند. متد `is_ip_blocked` نیز یک آیپی به عنوان ورودی گرفته و یک مقدار بولین برمیگرداند که نشان میدهد آیپی داده شده مسدود شده است یا نه.
همچنین دو مدل دیگر در این فایل قرار دارد که نباید در آنها تغییری ایجاد کنید.
### مدل `ViewDetail`
این مدل برای ذخیره کردن تمام ویوهای موجود در پروژه استفاده میشود. یعنی تمام ویوها به همراه *URL* شان را در ابتدای اجرا کردن پروژه، تعریف میکنیم و به دیتابیس اضافه میکنیم. با این کار به راحتی میتوانیم بفهمیم که هر آیپی با ریکوئست زدن به کدام ویو و *URL* مسدود شده است.
### مدل `SecurityConfig`
از این مدل نیز تنها یک نمونه ساخته میشود که در ابتدای اجرا کردن پروژه باید تعریف شود و دیگر تغییری نکند.
در این مدل میتوان لیست ویوهایی که میخواهیم از حمله مهاجامان در امان بماند را مشخص کرد.
</details>
<details class="green">
<summary>
فایل `init_guard.py`
</summary>
در این فایل باید یک دستور برای جنگو بنویسید که بتواند مقادیر اولیهی موردنیاز برای مدلهای `ViewDetail` و `SecurityConfig` را در صورتی که از قبل ساخته نشده باشند را بسازد و در دیتابیس قرار دهد.
</details>
<details class="green">
<summary>
فایل `admin.py`
</summary>
در این فایل نیز باید تنظیمات ادمین مربوط به مدلهای گفته شده در بالا را انجام دهید. نیازمندیهای ما به شکل زیر است:
+ لیست اشیاء `BlockedIp` را بتوان بر حسب فیلد `view` فیلتر کرد.
+ در لیست اشیاء `BlockedIp`، بتوان بر حسب آیپی، نام ویو و *URL* ویو جست و جو کرد.
+ برای قسمت ادمین `SecurityConfig`، اجازه ساختن و حذف کردن شئ جدید را به ادمینهای سایت ندهیم.
+ برای قسمت ادمین `ViewDetail`، اجازه ساختن، حذف کردن و تغییر دادن شئ را به ادمینهای سایت ندهیم.
</details>
<details class="green">
<summary>
فایل `middlewares.py`
</summary>
در این قسمت باید مهمترین عنصر این ماژول امنیتی جدید را پیاده کنید. یک *middleware* که مقدار ریکوئست بر ثانیه را برای هر ریکوئست محاسبه میکند و اگر این مقدار از حداکثر مقدار ممکن، یعنی ۴ ریکوئست بر ثانیه، بیشتر باشد، آیپی کاربر را مسدود میکند. در این میدلور باید بررسی شود که اگر آیپی کسی که ریکوئست زده است، قبلا مسدود شده بود (`banned_before`)، یک ریسپانس با کد ۴۰۳ برگرداند؛ همچنین در این میدلور برای ذخیره کردن ریکوئستهای هر کاربر، از کش جنگو با زمان ماندگاری (*timeout*) ۶۰ثانیه استفاده میشود نه دیتابیس، تا سرعت پاسخگویی به ریکوئستها خیلی تحت تاثیر قرار نگیرد.
هم چنین در متد `validate_request_per_second` باید دادههای مربوط به آیپی ریکوئست زننده که در کش ذخیره شده، بررسی و تعداد ریکوئستها بر ثانیهی آن محاسبه شود. اگر این مقدار بیشتر از ۴ ریکوئست بر ثانیه بود، آن وقت آیپی موردنظر را در لیست سیاه قرار داده و ریسپانسی با کد ۴۲۹ برگردانده شود.
</details>
حالا با اطلاعاتی که آقای رئیس به شما داده، کمکهایتان را برای ما آپلود کنید!
# آنچه باید آپلود کنید
یک فایل *ZIP* شامل پروژه جنگو خود آپلود کنید؛ توجه کنید که فقط میتوانید ۴ فایل گفته شده در بالا را تغییر دهید.