شرکت بورس ع.ش که بعد از کرونا مشتریهای زیادی پیدا کرده، با مشکلات جدیدی روبهرو شده!
زیاد شدن تعداد مشتریهای این شرکت بورس، باعث جلب توجه تعدادی از خرابکاران اینترنتی شده. این خرابکارها تصمیم گرفتند تا با حملههای **DDoS** به سایت این شرکت، آن را از دسترس خارج کنند و تنها به ازای گرفتن پولی هنگفت! از رئیس شرکت، دست از حمله بر میدارند.
شما باید به مدیر شرکت ع.ش کمک کنید تا با کمترین هزینه و با کمک دانش ملی و بومی! جلوی حملات این خرابکاران را بگیرد.
## پروژه اولیه
پروژه اولیه را از [این لینک](/problemset/assignments/4367/download_problem_initial_project/76279/) دانلود کنید. ساختار فایلهای این پروژه به صورت زیر است:
```
boors-va-corona
├── apps
│ ├── guard
│ │ ├── <mark class="yellow" title="این فایل را تغییر دهید"> > admin.py < </mark>
│ │ ├── apps.py
│ │ ├── __init__.py
│ │ ├── management
│ │ │ ├── commands
│ │ │ │ ├── <mark class="yellow" title="این فایل را تغییر دهید"> > init_guard.py < </mark>
│ │ │ │ └── __init__.py
│ │ │ └── __init__.py
│ │ ├── <mark class="yellow" title="این فایل را تغییر دهید"> > middlewares.py < </mark>
│ │ ├── migrations
│ │ ├── <mark class="yellow" title="این فایل را تغییر دهید"> > models.py < </mark>
│ │ ├── 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
```
فایلهایی که شما باید در این پروژه تکمیل کنید همگی در اپ `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>
حالا با اطلاعاتی که آقای رئیس به شما داده، کمکهایتان را برای ما آپلود کنید!
## تست نمونه
در فایلهای اولیهای که دانلود کردید یکسری داده اولیه به عنوان نمونه قرار داده شده است. میتوانید قبل از فرستادن سوال در سایت، این تستها را ببینید تا با نحوه داوری ما آشنا شوید و از پاسخ خود اطمینان حاصل نمایید.
تستها را میتوانید با دستور زیر اجرا کنید:
```shell terminal terminal
python manage.py test
```
## نکات
+ شما تنها مجوز ایجاد تغییرات در فایلهای زیر را دارید و **تمامی تغییرات دیگر شما** در فایلهای پروژه **نادیده گرفته خواهند شد.**
+ فایل `apps/guard/admin.py`
+ فایل `apps/guard/middlewares.py`
+ فایل `apps/guard/models.py`
+ فایل `apps/guard/management/commands/init_guard.py`
+ فراموش نکنید که میتوانید با مطالعهی `testsample.py` با روش تست کردن مدلها، فرمها و ادمینها آشنا شوید.
## نحوه ارسال
یک فایل _ZIP_ حاوی همهی فایلهای پروژه، آپلود کنید. نام فایل _ZIP_ اهمیتی ندارد.