جلوگیری از حذف کاربر admin در django

Django در حالت عادی اجزاه همه کاربرها رو میده. خیلی راحت کاربر ادمین از داشبود مدیریت میتونه همه کاربرها رو انتخاب و حذف کنه 🙂

خب خوشبینانه حتما دلیل برای این مورد وجود داره که من نمیدونم. ولی خب این مورد برای ما مساله ساز شده بود.

مشتری ما که اطلاعات فنی زیادی نداره چند بار اشتباها برای حذف یوزرهای تستی که بعد از تحویل پروژه ایجاد کرده بود کل یوزرها رو انتخاب و حذف کرده بود. در این حالت براحتی از طریق ترمینال با دستور زیر میتونید یک یوزر admin ایجاد کنید.

python manage.py createsuperuser

حالا راهکار برای جلوگیری از بروز این مشکل چیه؟

تو django یه ویژگی بسیار کاربردی به نام signal وجود داره و کارش اینه که میتونه هوک بشه به یکسری رویدادهای از پیش تعیین شده یا رویدادهای کاستوم که خودمون تعریف میکنیم.
مثلا میتونیم هوک کنیم به رویداد pre_delete که توسط خود Django ایجاد شده.در این حالت میتونیم قبل از حذف رکورد/رکوردهای یک مدل مشخص یک پردازش انجام بدیم و در یک شرایط خاص (مثلا اینکه رکورد مورد نظر ما یک کاربر ادمین هستش) نذاریم action در حال اجرا به اتمام برسه (یوزر پاک بشه).

طبق مثالی که زدم برای جلوگیری از حذف کاربر admin میتونیم از سیگنال pre_delete استفاده کنیم.

قطعه کد زیر رو توی models.py اپلیکیشن users قرار بدید و در ادامه توضیح کد رو بخونید:

@receiver(pre_delete, sender=User)
def delete_user(sender, instance, **kwargs):
    if instance.is_superuser and instance.username == 'admin':
        raise PermissionDenied

تو خط اول متدمون رو هوک میکنیم به سیگنال pre_delete و مدل User رو به عنوان پارامتر sender معرفی می کنیم. یعنی مدل User رو چک کن و قبل از حذف هر ریکورد متد من رو یکبار اجرا کن.

پارامترهای sender که اینجا همون مدل User هستش و instance که رکورد در حال حذف هستش به متد ما پاس داده میشه.

در خط های بعد نام کاربری رو(به شرط سوپریوزر بودن) چک میکنیم و اگر برابر admin بود PermissionDenied میدیم که در نتیجه صفحه permission denied به کاربر نشون داده میشه.

خوش باشی دولوپر جان 🙂

کانفیگ سرویس گانیکارن برای یک پروژه django روی Centos

ایجاد سرویس در لینوکس با یک فایل کانفیگ با پسوند service امکان پذیره. الان میخوایم یه سرویس برای گانیکارن ایجاد کنیم.

۱- یه فایل به نام gunicorn.service در مسیر system به صورت زیر ایجاد می کنیم.

nano /etc/systemd/system/gunicorn.service

۲- فایل های سرویس شامل یک سری بلوک هستند که هر بلوک تنظیماتی رو برای سرویس ما نگه داری میکنه. اولین بلوک Unit هستش که بصورت زیر نوشته میشه:

[Unit]
Descripttion=gunicorn daemon
After=network.target

۳- بلوک دوم Service هستش که بصورت زیر نوشته میشه

[Service]
User=unixusername
Group=nginx
WorkingDirectory=/home/unixusername/django_application
ExecStart=/home/unixusername/django_application/venv/bin/gunicorn -b 127.0.0.1:9001 --access-logfile '-' -w 1 django_application.wsgi &

تو بلوک سرویس ابتدا کاربر و گروهی که قراره پروسس اپلیکیشن رو برای ما انجام بدن و دسترسی به دایرکتوری پروژه رو داشته باشه معرفی می کنیم.

بعد از اون برای پارامتر WorkingDirectory آدرس دایرکتوری پروژه رو به سرویس میدیم. این آدرس مسیری هستش که فایل mange.py توش قرار گرفته.

و در انتها برای پارامتر ExecStart کامند اجرای Gunicorn با پارامترهای مد نظر خودمون رو قرار میدیم. توضیحات پارامترهای Gunicorn رو می تونید از داکیومنتش بخونید.

۴- بلوک آخر Install هستش که به systemd لینوکس میگه که اگر سرویس enable شد چه زمانی باید اجرا بشه. که ما بهش میگم هر وقت multi-user بوت شد و در حال اجرا بود سرویس ما رو هم ران کن. دقیقا به صورت زیر بنویسید:

[Install]
WantedBy=multi-user.target

در نهایت فایل gunicorn.service بصورت زیر میشه:

[Unit]
Descripttion=gunicorn daemon
After=network.target

[Service]
User=unixusername
Group=nginx
WorkingDirectory=/home/unixusername/django_application
ExecStart=/home/unixusername/django_application/venv/bin/gunicorn -b 127.0.0.1:9001 --access-logfile '-' -w 1 django_application.wsgi &

[Install]
WantedBy=multi-user.target

۵- با دستو زیر می تونید سرویس رو استارت کنید

systemctl start gunicorn

۶- و با دستور زیر سرویس رو فعال کنید که بعد از ریبوت سیستم عامل بتونه مجدد اجرا بشه

systemctl enable gunicorn

۷- با استارت سرویس gunicron باید اپلیکیشن django روی پورت مورد نظر(تو این مثال 9001) در دسترس باشه. یکبار برای اطمینان از عملکرد صحیح سرویسی که ایجاد کردید سیستم عامل رو ریبوت کنید.